#pragma once
#ifndef __AUTO_THREAD__
#define __AUTO_THREAD__
#include "AutoDefs.h"
namespace Auto {
class MemoryScanner;
class Zone;
#if defined(__ppc__) || defined(__ppc64__)
class NonVolatileRegisters {
private:
enum {
first_nonvolatile_register = 13, number_of_nonvolatile_registers = 32 - first_nonvolatile_register,
};
usword_t _registers[number_of_nonvolatile_registers];
static inline void capture_registers(register usword_t *registers) {
#if defined(__ppc__)
__asm__ volatile ("stmw r13,0(%[registers])" : : [registers] "b" (registers) : "memory");
#else
__asm__ volatile ("std r13,0(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r14,8(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r15,16(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r16,24(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r17,32(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r18,40(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r19,48(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r20,56(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r21,64(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r22,72(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r23,80(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r24,88(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r25,96(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r26,104(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r27,112(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r28,120(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r29,128(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r30,136(%[registers])" : : [registers] "b" (registers) : "memory");
__asm__ volatile ("std r31,144(%[registers])" : : [registers] "b" (registers) : "memory");
#endif
}
public:
NonVolatileRegisters() { capture_registers(_registers); }
inline Range buffer_range() { return Range(_registers, sizeof(_registers)); }
};
#elif defined(__i386__)
class NonVolatileRegisters {
private:
usword_t _registers[5];
static inline void capture_registers(register usword_t *registers) {
__asm__ volatile ("mov %%ebx, 0(%[registers]) \n"
"mov %%ebp, 4(%[registers]) \n"
"mov %%esp, 8(%[registers]) \n"
"mov %%esi, 12(%[registers]) \n"
"mov %%edi, 16(%[registers]) \n"
: : [registers] "a" (registers) : "memory");
}
public:
NonVolatileRegisters() { capture_registers(_registers); }
inline Range buffer_range() { return Range(_registers, sizeof(_registers)); }
};
#elif defined(__x86_64__)
class NonVolatileRegisters {
private:
usword_t _registers[7];
static inline void capture_registers(register usword_t *registers) {
__asm__ volatile ("movq %%rbx, 0(%[registers]) \n"
"movq %%rsp, 8(%[registers]) \n"
"movq %%rbp, 16(%[registers]) \n"
"movq %%r12, 24(%[registers]) \n"
"movq %%r13, 32(%[registers]) \n"
"movq %%r14, 40(%[registers]) \n"
"movq %%r15, 48(%[registers]) \n"
: : [registers] "a" (registers) : "memory");
}
public:
NonVolatileRegisters() { capture_registers(_registers); }
inline Range buffer_range() { return Range(_registers, sizeof(_registers)); }
};
#else
#error Unknown Architecture
#endif
class Thread : public AuxAllocated {
private:
Thread *_next; Zone *_zone; pthread_t _pthread; mach_port_t _thread; void *_stack; bool _exiting; bool _deadPort; uint32_t _suspended; uint32_t _retains;
void scan_current_thread(MemoryScanner &scanner);
void scan_other_thread(MemoryScanner &scanner);
public:
Thread(Zone *zone, pthread_t pthread, mach_port_t thread)
: _next(NULL), _zone(zone), _pthread(pthread), _thread(thread), _stack(pthread_get_stackaddr_np(pthread)),
_exiting(false), _deadPort(false), _suspended(0), _retains(0)
{
}
inline Thread *next() { return _next; }
inline Zone *zone() { return _zone; }
inline pthread_t pthread() { return _pthread; }
inline mach_port_t thread() { return _thread; }
inline bool is_exiting() { return _exiting; }
inline void set_next(Thread *next) { _next = next; }
inline void set_is_exiting() { _exiting = true; }
inline void retain() { ++_retains; }
inline uint32_t release() { return --_retains; }
inline bool deadPort() { return _deadPort; }
inline bool is_current_thread() const {
return pthread_self() == _pthread;
}
inline void unlink(Thread **link) {
for (Thread *t = *link; t; link = &t->_next, t = *link) {
if (t == this) {
*link = t->_next;
break;
}
}
}
void scan_thread_with_suspend_and_closure(MemoryScanner &scanner);
void scan_thread_without_suspend(MemoryScanner &scanner);
bool suspend();
bool resume();
static void destroy_registered_thread(void *data);
};
};
#endif // __AUTO_THREAD__