#include "u.h"#include <errno.h>#include <sys/time.h>#include <sys/types.h>#ifndef __MINGW32__#include <sys/wait.h>#include <sched.h>#endif#include <signal.h>#if !defined(__OpenBSD__) && !defined(__MINGW32__)# include <ucontext.h>#endif#ifdef __MINGW32__# include <mingw32.h># include <mingwutil.h>#else# include <sys/utsname.h>#endif#include "libc.h"#include "thread.h" #if defined(__FreeBSD__) && __FreeBSD__ < 5extern int getmcontext(mcontext_t*);extern void setmcontext(mcontext_t*);#define setcontext(u) setmcontext(&(u)->uc_mcontext)#define getcontext(u) getmcontext(&(u)->uc_mcontext)extern int swapcontext(ucontext_t*, ucontext_t*);extern void makecontext(ucontext_t*, void(*)(), int, ...);#endif #if defined(__APPLE__) || defined(__MINGW32__) /* * OS X before 10.5 (Leopard) does not provide * swapcontext nor makecontext, so we have to use our own. * In theory, Leopard does provide them, but when we use * them, they seg fault. Maybe we're using them wrong. * So just use our own versions, even on Leopard. */# define mcontext libthread_mcontext# define mcontext_t libthread_mcontext_t# define ucontext libthread_ucontext# define ucontext_t libthread_ucontext_t# define swapcontext libthread_swapcontext# define makecontext libthread_makecontext# if defined(__i386__)# include "386-ucontext.h"# else# include "power-ucontext.h"# endif#endif #if defined(__OpenBSD__)# define mcontext libthread_mcontext# define mcontext_t libthread_mcontext_t# define ucontext libthread_ucontext# define ucontext_t libthread_ucontext_t# if defined __i386__# include "386-ucontext.h"# else# include "power-ucontext.h"# endifextern pid_t rfork_thread(int, void*, int(*)(void*), void*);#endif /* THIS DOES NOT WORK! Don't do this!(At least, not on Solaris. Maybe this is right for Linux,in which case it should say if defined(__linux__) && defined(__sun__),but surely the latter would be defined(__sparc__). #if defined(__sun__)# define mcontext libthread_mcontext# define mcontext_t libthread_mcontext_t# define ucontext libthread_ucontext# define ucontext_t libthread_ucontext_t# include "sparc-ucontext.h"#endif*/ #if defined(__arm__)int getmcontext(mcontext_t*);void setmcontext(const mcontext_t*);#define setcontext(u) setmcontext(&(u)->uc_mcontext)#define getcontext(u) getmcontext(&(u)->uc_mcontext)#endif typedef struct Context Context;typedef struct Execjob Execjob;typedef struct Proc Proc;typedef struct _Procrendez _Procrendez; typedef struct Jmp Jmp;struct Jmp{ p9jmp_buf b;}; enum{ STACK = 8192}; struct Context{ ucontext_t uc;}; struct Execjob{ int *fd; char *cmd; char **argv; char *dir; Channel *c;}; struct _Thread{ _Thread *next; _Thread *prev; _Thread *allnext; _Thread *allprev; Context context; uint id; uchar *stk; uint stksize; int exiting; void (*startfn)(void*); void *startarg; Proc *proc; char name[256]; char state[256]; void *udata; Alt *alt;}; struct _Procrendez{ Lock *l; int asleep;#ifdef PLAN9PORT_USING_PTHREADS pthread_cond_t cond;#elif defined(__MINGW32__) HANDLE cond;#else int pid;#endif}; extern void _procsleep(_Procrendez*);extern void _procwakeup(_Procrendez*);extern void _procwakeupandunlock(_Procrendez*); struct Proc{ Proc *next; Proc *prev; char msg[128];#ifdef PLAN9PORT_USING_PTHREADS pthread_t osprocid;#else int osprocid;#endif Lock lock; int nswitch; _Thread *thread; _Thread *pinthread; _Threadlist runqueue; _Threadlist idlequeue; _Threadlist allthreads; uint nthread; uint sysproc; _Procrendez runrend; Context schedcontext; void *udata; Jmp sigjmp; int mainproc;}; #define proc() _threadproc()#define setproc(p) _threadsetproc(p) extern Proc *_threadprocs;extern Lock _threadprocslock;extern Proc *_threadexecproc;extern Channel *_threadexecchan;extern QLock _threadexeclock;extern Channel *_dowaitchan; extern void _procstart(Proc*, void (*fn)(Proc*));extern _Thread *_threadcreate(Proc*, void(*fn)(void*), void*, uint);extern void _threadexit(void);extern Proc *_threadproc(void);extern void _threadsetproc(Proc*);extern int _threadlock(Lock*, int, ulong);extern void _threadunlock(Lock*, ulong);extern void _pthreadinit(void);extern int _threadspawn(int*, char*, char**, char*);extern int _runthreadspawn(int*, char*, char**, char*);extern void _threadsetupdaemonize(void);extern void _threaddodaemonize(char*);extern void _threadpexit(void);extern void _threaddaemonize(void);
#include "u.h"
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#ifndef __MINGW32__
#include <sys/wait.h>
#include <sched.h>
#endif
#include <signal.h>
#if !defined(__OpenBSD__) && !defined(__MINGW32__)
# include <ucontext.h>
#endif
#ifdef __MINGW32__
# include <mingw32.h>
# include <mingwutil.h>
#else
# include <sys/utsname.h>
#endif
#include "libc.h"
#include "thread.h"
#if defined(__FreeBSD__) && __FreeBSD__ < 5
extern int getmcontext(mcontext_t*);
extern void setmcontext(mcontext_t*);
#define setcontext(u) setmcontext(&(u)->uc_mcontext)
#define getcontext(u) getmcontext(&(u)->uc_mcontext)
extern int swapcontext(ucontext_t*, ucontext_t*);
extern void makecontext(ucontext_t*, void(*)(), int, ...);
#endif
#if defined(__APPLE__) || defined(__MINGW32__)
/*
* OS X before 10.5 (Leopard) does not provide
* swapcontext nor makecontext, so we have to use our own.
* In theory, Leopard does provide them, but when we use
* them, they seg fault. Maybe we're using them wrong.
* So just use our own versions, even on Leopard.
*/
# define mcontext libthread_mcontext
# define mcontext_t libthread_mcontext_t
# define ucontext libthread_ucontext
# define ucontext_t libthread_ucontext_t
# define swapcontext libthread_swapcontext
# define makecontext libthread_makecontext
# if defined(__i386__)
# include "386-ucontext.h"
# else
# include "power-ucontext.h"
# endif
#endif
#if defined(__OpenBSD__)
# define mcontext libthread_mcontext
# define mcontext_t libthread_mcontext_t
# define ucontext libthread_ucontext
# define ucontext_t libthread_ucontext_t
# if defined __i386__
# include "386-ucontext.h"
# else
# include "power-ucontext.h"
# endif
extern pid_t rfork_thread(int, void*, int(*)(void*), void*);
#endif
/* THIS DOES NOT WORK! Don't do this!
(At least, not on Solaris. Maybe this is right for Linux,
in which case it should say if defined(__linux__) && defined(__sun__),
but surely the latter would be defined(__sparc__).
#if defined(__sun__)
# define mcontext libthread_mcontext
# define mcontext_t libthread_mcontext_t
# define ucontext libthread_ucontext
# define ucontext_t libthread_ucontext_t
# include "sparc-ucontext.h"
#endif
*/
#if defined(__arm__)
int getmcontext(mcontext_t*);
void setmcontext(const mcontext_t*);
#define setcontext(u) setmcontext(&(u)->uc_mcontext)
#define getcontext(u) getmcontext(&(u)->uc_mcontext)
#endif
typedef struct Context Context;
typedef struct Execjob Execjob;
typedef struct Proc Proc;
typedef struct _Procrendez _Procrendez;
typedef struct Jmp Jmp;
struct Jmp
{
p9jmp_buf b;
};
enum
{
STACK = 8192
};
struct Context
{
ucontext_t uc;
};
struct Execjob
{
int *fd;
char *cmd;
char **argv;
char *dir;
Channel *c;
};
struct _Thread
{
_Thread *next;
_Thread *prev;
_Thread *allnext;
_Thread *allprev;
Context context;
uint id;
uchar *stk;
uint stksize;
int exiting;
void (*startfn)(void*);
void *startarg;
Proc *proc;
char name[256];
char state[256];
void *udata;
Alt *alt;
};
struct _Procrendez
{
Lock *l;
int asleep;
#ifdef PLAN9PORT_USING_PTHREADS
pthread_cond_t cond;
#elif defined(__MINGW32__)
HANDLE cond;
#else
int pid;
#endif
};
extern void _procsleep(_Procrendez*);
extern void _procwakeup(_Procrendez*);
extern void _procwakeupandunlock(_Procrendez*);
struct Proc
{
Proc *next;
Proc *prev;
char msg[128];
#ifdef PLAN9PORT_USING_PTHREADS
pthread_t osprocid;
#else
int osprocid;
#endif
Lock lock;
int nswitch;
_Thread *thread;
_Thread *pinthread;
_Threadlist runqueue;
_Threadlist idlequeue;
_Threadlist allthreads;
uint nthread;
uint sysproc;
_Procrendez runrend;
Context schedcontext;
void *udata;
Jmp sigjmp;
int mainproc;
};
#define proc() _threadproc()
#define setproc(p) _threadsetproc(p)
extern Proc *_threadprocs;
extern Lock _threadprocslock;
extern Proc *_threadexecproc;
extern Channel *_threadexecchan;
extern QLock _threadexeclock;
extern Channel *_dowaitchan;
extern void _procstart(Proc*, void (*fn)(Proc*));
extern _Thread *_threadcreate(Proc*, void(*fn)(void*), void*, uint);
extern void _threadexit(void);
extern Proc *_threadproc(void);
extern void _threadsetproc(Proc*);
extern int _threadlock(Lock*, int, ulong);
extern void _threadunlock(Lock*, ulong);
extern void _pthreadinit(void);
extern int _threadspawn(int*, char*, char**, char*);
extern int _runthreadspawn(int*, char*, char**, char*);
extern void _threadsetupdaemonize(void);
extern void _threaddodaemonize(char*);
extern void _threadpexit(void);
extern void _threaddaemonize(void);