00001
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #if CMK_HAS_ALLOCA_H
00010 # include <alloca.h>
00011 #endif
00012
00013 #include "uJcontext.h"
00014 #ifdef _MSC_VER
00015 # define alloca _alloca
00016 #endif
00017
00018 #ifdef __MINGW_H
00019 #error "not supported under cygwin and mingw!"
00020 #endif
00021
00022
00023 #define VERBOSE(x)
00024
00025 #if CMK_HAS_UNDERSCORE_SETJMP
00026 #define SETJMP _setjmp
00027 #define LONGJMP _longjmp
00028 #else
00029 #define SETJMP setjmp
00030 #define LONGJMP longjmp
00031 #endif
00032
00033
00034 static void *getStack(void) {
00035 int x = 0;
00036 void *p=&x;
00037 return p;
00038 }
00039
00040 VERBOSE(
00041 static void printStack(void) {
00042 printf(" from stack %p\n",getStack());
00043 }
00044 )
00045
00046 static void threadFatal(const char *why) {
00047 fprintf(stderr,"Fatal thread error in uJcontext> %s\n",why);
00048 exit(1);
00049 }
00050
00051
00052 int getJcontext (uJcontext_t *u)
00053 {
00054 u->uc_link=0;
00055 u->uc_stack.ss_sp=getStack();
00056 u->uc_stack.ss_size=0;
00057 u->uc_stack.ss_flags=0;
00058 u->uc_flags=0;
00059 u->uc_sigmask=0;
00060 u->uc_swap=0;
00061 u->_uc_fn=NULL;
00062 u->_uc_args[0]=u->_uc_args[1]=NULL;
00063 return 0;
00064 }
00065
00066
00067 char *_dummyAllocaSetJcontext;
00068
00069
00070 int setJcontext (const uJcontext_t *u)
00071 {
00072 uJcontext_t *mu=(uJcontext_t *)u;
00073
00074 CmiAssert (mu != NULL);
00075
00076
00077 if (mu->uc_swap) mu->uc_swap(mu);
00078
00079 if (mu->_uc_fn==NULL)
00080 {
00081 LONGJMP(mu->_uc_jmp_buf,0);
00082 threadFatal("Fatal error performing longjmp");
00083 }
00084 else
00085 {
00086
00087 char *new_sp=(char *)mu->uc_stack.ss_sp;
00088
00095 int caller_distance=8*sizeof(void *);
00096
00097 uJcontext_fn_t mu_fn=mu->_uc_fn;
00098 mu->_uc_fn=NULL;
00099
00100
00101 new_sp+=mu->uc_stack.ss_size-caller_distance;
00102
00103 #ifndef CMK_BLUEGENEQ
00104 VERBOSE( printf("About to switch to stack %p ",new_sp); printStack(); )
00105 if (1) {
00106 #ifdef _MSC_VER
00107
00117 __asm { mov esp, new_sp };
00118 #elif 0 && defined(__APPLE__) && CMK_64BIT
00119 asm ( "mov %0, %%rsp\n"::"m"(new_sp));
00120 #else
00121 char *old_sp = NULL;
00122 CmiInt8 allocLen;
00123 old_sp = (char *)&old_sp;
00124 allocLen=old_sp-new_sp;
00125
00126 VERBOSE( printf("calling alloca with %lld", allocLen); printStack(); )
00127 _dummyAllocaSetJcontext = (char *)alloca(allocLen);
00128 #endif
00129 }
00130 VERBOSE( printf("After alloca"); printStack(); )
00131
00132 mu_fn(mu->_uc_args[0],mu->_uc_args[1]);
00133
00134
00135 if (mu->uc_link!=0)
00136 setJcontext(mu->uc_link);
00137 else
00138 threadFatal("uc_link not set-- thread should never return");
00139 #else
00140
00141 uint64_t startiar = *((uint64_t*)mu_fn);
00142
00143 asm volatile("mr 3, %0;"
00144 "mtlr 3;"
00145 "mr 1, %1;"
00146 "mr 3, %2;"
00147 "mr 4, %3;"
00148 "blr;"
00149 : : "r" (startiar), "r" (new_sp), "r" (mu->_uc_args[0]), "r" (mu->_uc_args[1]) : "r1", "r3", "r4", "memory");
00150
00151
00152 startiar = *((uint64_t*)setJcontext);
00153 asm volatile("mr 3, %0;"
00154 "mtlr 3;"
00155 "mr 3, %1;"
00156 "blr;"
00157 : : "r" (startiar), "r" (mu->uc_link) : "r3", "memory");
00158 #endif
00159
00160 }
00161 return 0;
00162 }
00163
00164
00165
00166 int swapJcontext (uJcontext_t *o,
00167 const uJcontext_t *u)
00168 {
00169 uJcontext_t *mu=(uJcontext_t *)u;
00170 VERBOSE( printf("swapJcontext(%p,%p)",o,u); printStack(); )
00171 if (0==SETJMP(o->_uc_jmp_buf))
00172 setJcontext(mu);
00173 else {
00174 VERBOSE( printf("swapJcontext returning to %p",mu); printStack(); )
00175 }
00176 return 0;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 void makeJcontext (uJcontext_t *u, uJcontext_fn_t __func,
00186 int __argc, void *a,void *b)
00187 {
00188 VERBOSE( printf("makeJcontext(%p)",u); printStack(); )
00189 u->_uc_fn=__func;
00190 u->_uc_args[0]=a;
00191 u->_uc_args[1]=b;
00192 }
00193
00194
00195