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