3 #include "structdefs.h"
10 #include "methodheaders.h"
12 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
18 #include "DSTM/interface_recovery/dstm.h"
19 #include "DSTM/interface_recovery/altprelookup.h"
22 extern int numRecovery;
23 extern unsigned int deadMachine[8];
24 extern unsigned int sizeOfRedupedData[8];
25 extern double elapsedTime[8];
29 #include "DSTM/interface/dstm.h"
30 #include "DSTM/interface/altprelookup.h"
31 #include "DSTM/interface/prefetch.h"
39 #define ARRAY_LENGTH 700003
41 __thread int event[ARRAY_LENGTH];
42 __thread unsigned long long clkticks[ARRAY_LENGTH];
43 unsigned long long beginClock=0;
44 #define FILENAME "log"
48 __thread int objcount=0;
49 #define ASSIGNUID(x) { \
50 int number=((objcount++)<<EVTHREADSHIFT)|threadnum; \
57 #if defined(THREADS)||defined(STM)
58 /* Global barrier for STM */
59 pthread_barrier_t barrier;
60 pthread_barrierattr_t attr;
68 #define GCPOINT(x) ((INTPTR)((x)*0.99))
71 extern int classsize[];
72 extern int typearray[];
73 extern int typearray2[];
74 jmp_buf error_handler;
79 float failurechance=0;
82 int injectinstructionfailures;
84 float instfailurechance=0;
87 typedef unsigned long long ticks;
92 int instanceof(struct ___Object___ *ptr, int type) {
104 i=typearray2[i-NUMCLASSES];
110 void exithandler(int sig, siginfo_t *info, void * uap) {
114 void initializeexithandler() {
115 struct sigaction sig;
116 sig.sa_sigaction=&exithandler;
117 sig.sa_flags=SA_SIGINFO;
118 sigemptyset(&sig.sa_mask);
119 sigaction(SIGUSR2, &sig, 0);
123 /* This function inject failures */
125 void injectinstructionfailure() {
127 if (injectinstructionfailures) {
130 instructioncount=failurecount;
131 instaccum+=failurecount;
132 if ((((double)random())/RAND_MAX)<instfailurechance) {
135 printf("FAILURE!!! %d\n",numfailures);
136 longjmp(error_handler,11);
141 if (injectinstructionfailures) {
144 instaccum+=failurecount;
145 if ((((double)random())/RAND_MAX)<instfailurechance) {
148 printf("FAILURE!!! %d\n",numfailures);
156 #ifdef D___Double______nativeparsedouble____L___String___
157 double CALL01(___Double______nativeparsedouble____L___String___,struct ___String___ * ___str___) {
158 int length=VAR(___str___)->___count___;
159 int maxlength=(length>60)?60:length;
160 char str[maxlength+1];
161 struct ArrayObject * chararray=VAR(___str___)->___value___;
163 int offset=VAR(___str___)->___offset___;
164 for(i=0; i<maxlength; i++) {
165 str[i]=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
173 #ifdef D___Double______nativeparsedouble_____AR_B_I_I
174 double CALL23(___Double______nativeparsedouble_____AR_B_I_I, int start, int length,int start,int length,struct ArrayObject * ___str___) {
175 int maxlength=(length>60)?60:length;
176 char str[maxlength+1];
177 struct ArrayObject * bytearray=VAR(___str___);
179 for(i=0; i<maxlength; i++) {
180 str[i]=(((char *)&bytearray->___length___)+sizeof(int))[i+start];
188 #ifdef D___Double______doubleToRawLongBits____D
200 long long CALL11(___Double______doubleToRawLongBits____D, double dval, double dval) {
204 #if defined(__IEEE_BYTES_LITTLE_ENDIAN)
205 /* On little endian ARM processors when using FPA, word order of
206 doubles is still big endian. So take that into account here. When
207 using VFP, word order of doubles follows byte order. */
209 #define SWAP_DOUBLE(a) (((a) << 32) | (((a) >> 32) & 0x00000000ffffffff))
211 val.j = SWAP_DOUBLE(val.j);
218 #ifdef D___Double______longBitsToDouble____J
219 double CALL11(___Double______longBitsToDouble____J, long long lval, long long lval) {
223 #if defined(__IEEE_BYTES_LITTLE_ENDIAN)
225 #define SWAP_DOUBLE(a) (((a) << 32) | (((a) >> 32) & 0x00000000ffffffff))
227 val.j = SWAP_DOUBLE(val.j);
234 #ifdef D___String______convertdoubletochar____D__AR_C
235 int CALL12(___String______convertdoubletochar____D__AR_C, double ___val___, double ___val___, struct ArrayObject ___chararray___) {
236 int length=VAR(___chararray___)->___length___;
239 int num=snprintf(str, length, "%f",___val___);
242 for(i=0; i<length; i++) {
243 ((short *)(((char *)&VAR(___chararray___)->___length___)+sizeof(int)))[i]=(short)str[i];
248 #ifdef D___System______deepArrayCopy____L___Object____L___Object___
249 void deepArrayCopy(struct ___Object___ * dst, struct ___Object___ * src) {
250 int dsttype=((int *)dst)[0];
251 int srctype=((int *)src)[0];
253 src=src->___objlocation___;
255 if (dsttype<NUMCLASSES||srctype<NUMCLASSES||srctype!=dsttype)
257 struct ArrayObject *aodst=(struct ArrayObject *)dst;
258 struct ArrayObject *aosrc=(struct ArrayObject *)src;
259 int dstlength=aodst->___length___;
260 int srclength=aosrc->___length___;
261 if (dstlength!=srclength)
263 unsigned INTPTR *pointer=pointerarray[srctype];
265 int elementsize=classsize[srctype];
266 int size=srclength*elementsize;
268 memcpy(((char *)&aodst->___length___)+sizeof(int) , ((char *)&aosrc->___length___)+sizeof(int), size);
272 for(i=0;i<srclength;i++) {
273 struct ___Object___ * ptr=((struct ___Object___**)(((char*) &aosrc->___length___)+sizeof(int)))[i];
274 int ptrtype=((int *)ptr)[0];
275 if (ptrtype>=NUMCLASSES) {
276 struct ___Object___ * dstptr=((struct ___Object___**)(((char*) &aodst->___length___)+sizeof(int)))[i];
277 deepArrayCopy(dstptr,ptr);
280 ((struct ___Object___ **)(((char*) &aodst->___length___)+sizeof(int)))[i]=ptr;
286 void CALL02(___System______deepArrayCopy____L___Object____L___Object___, struct ___Object___ * ___dst___, struct ___Object___ * ___src___) {
287 deepArrayCopy(VAR(___dst___), VAR(___src___));
291 #ifdef D___System______arraycopy____L___Object____I_L___Object____I_I
292 void arraycopy(struct ___Object___ *src, int srcPos, struct ___Object___ *dst, int destPos, int length) {
293 int dsttype=((int *)dst)[0];
294 int srctype=((int *)src)[0];
296 //not an array or type mismatch
297 if (dsttype<NUMCLASSES||srctype<NUMCLASSES)
299 if (srctype!=dsttype)
300 printf("Potential type mismatch in arraycopy\n");
302 struct ArrayObject *aodst=(struct ArrayObject *)dst;
303 struct ArrayObject *aosrc=(struct ArrayObject *)src;
304 int dstlength=aodst->___length___;
305 int srclength=aosrc->___length___;
309 if (srcPos+length>srclength)
311 if (destPos+length>dstlength)
314 unsigned INTPTR *pointer=pointerarray[srctype];
316 int elementsize=classsize[srctype];
317 int size=length*elementsize;
319 memcpy(((char *)&aodst->___length___)+sizeof(int)+destPos*elementsize, ((char *)&aosrc->___length___)+sizeof(int)+srcPos*elementsize, size);
323 for(i=0;i<length;i++) {
324 struct ___Object___ * ptr=((struct ___Object___**)(((char*) &aosrc->___length___)+sizeof(int)))[i+srcPos];
326 ((struct ___Object___ **)(((char*) &aodst->___length___)+sizeof(int)))[i+destPos]=ptr;
331 void CALL35(___System______arraycopy____L___Object____I_L___Object____I_I, int ___srcPos___, int ___destPos___, int ___length___, struct ___Object___ * ___src___, int ___srcPos___, struct ___Object___ * ___dst___, int ___destPos___, int ___length___) {
332 arraycopy(VAR(___src___), ___srcPos___, VAR(___dst___), ___destPos___, ___length___);
336 #ifdef D___Runtime______availableProcessors____
337 int CALL01(___Runtime______availableProcessors____, struct ___Runtime___ * ___this___) {
338 printf("Unimplemented Runtime.availableProcessors\n");
343 #ifdef D___Runtime______freeMemory____
344 long long CALL01(___Runtime______freeMemory____, struct ___Runtime___ * ___this___) {
345 printf("Unimplemented Runtime.freeMemory\n");
346 return 1024*1024*1024;
350 #ifdef D___Runtime______totalMemory____
351 long long CALL01(___Runtime______totalMemory____, struct ___Runtime___ * ___this___) {
352 printf("Unimplemented Runtime.totalMemory\n");
353 return 1024*1024*1024;
357 #ifdef D___Runtime______maxMemory____
358 long long CALL01(___Runtime______maxMemory____, struct ___Runtime___ * ___this___) {
359 printf("Unimplemented Runtime.maxMemory\n");
360 return 1024*1024*1024;
364 void CALL11(___System______exit____I,int ___status___, int ___status___) {
367 printf("numTransCommit = %d\n", numTransCommit);
368 printf("numTransAbort = %d\n", numTransAbort);
369 printf("nSoftAbort = %d\n", nSoftAbort);
372 printf("nSoftAbortCommit = %d\n", nSoftAbortCommit);
373 printf("nSoftAbortAbort = %d\n", nSoftAbortAbort);
376 for(i=0; i<TOTALNUMCLASSANDARRAY; i++) {
377 printf("typesCausingAbort[%2d] numaccess= %5d numabort= %3d\n", i, typesCausingAbort[i].numaccess, typesCausingAbort[i].numabort);
388 void CALL11(___System______logevent____I,int ___event___, int ___event___) {
390 event[counter] = ___event___;
391 clkticks[counter] = rdtsc();
397 void CALL00(___System______logevent____) {
404 void CALL11(___System______flushToFile____I, int ___threadid___, int ___threadid___) {
409 memset(filename, 0, 20);
410 sprintf(filename, "%s_%d", FILENAME, ___threadid___);
411 if ((fp = fopen(filename, "w+")) == NULL) {
416 for (i = 0; i < counter-1; i++) {
417 fprintf(fp, "%d %lld %lld\n", event[i], clkticks[i]-beginClock, clkticks[i+1]-beginClock);
419 fprintf(fp, "%d %lld\n", event[i], clkticks[i]-beginClock);
426 void CALL00(___System______initLog____) {
430 for(i=0; i<ARRAY_LENGTH; i++) {
439 #ifdef D___Vector______removeElement_____AR_L___Object____I_I
440 void CALL23(___Vector______removeElement_____AR_L___Object____I_I, int ___index___, int ___size___, struct ArrayObject * ___array___, int ___index___, int ___size___) {
441 char* offset=((char *)(&VAR(___array___)->___length___))+sizeof(unsigned int)+sizeof(void *)*___index___;
442 memmove(offset, offset+sizeof(void *),(___size___-___index___-1)*sizeof(void *));
446 void CALL11(___System______printI____I,int ___status___, int ___status___) {
447 printf("%d\n",___status___);
450 long long CALL00(___System______currentTimeMillis____) {
451 struct timeval tv; long long retval;
452 gettimeofday(&tv, NULL);
453 retval = tv.tv_sec; /* seconds */
454 retval*=1000; /* milliseconds */
455 retval+= (tv.tv_usec/1000); /* adjust milliseconds & add them in */
459 #ifdef D___System______gc____
460 void CALL00(___System______gc____) {
461 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
462 while (pthread_mutex_trylock(&gclock)!=0) {
463 stopforgc((struct garbagelist *)___params___);
468 /* Grow the to heap if necessary */
470 INTPTR curr_heapsize=curr_heaptop-curr_heapbase;
471 INTPTR to_heapsize=to_heaptop-to_heapbase;
473 if (curr_heapsize>to_heapsize) {
475 to_heapbase=malloc(curr_heapsize);
476 if (to_heapbase==NULL) {
477 printf("Error Allocating enough memory\n");
480 to_heaptop=to_heapbase+curr_heapsize;
481 to_heapptr=to_heapbase;
486 collect((struct garbagelist *)___params___);
489 void * tmp=to_heapbase;
490 to_heapbase=curr_heapbase;
494 to_heaptop=curr_heaptop;
498 curr_heapptr=to_heapptr;
499 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
500 to_heapptr=to_heapbase;
501 bzero(tmp, curr_heaptop-tmp);
505 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
506 pthread_mutex_unlock(&gclock);
511 long long CALL00(___System______microTimes____) {
514 gettimeofday(&tv, NULL);
515 retval = tv.tv_sec; /* seconds */
516 retval*=1000000; /* microsecs */
517 retval+= (tv.tv_usec); /* adjust microseconds & add them in */
521 long long CALL00(___System______getticks____) {
524 asm volatile("rdtsc" : "=a" (a), "=d" (d));
525 return (((ticks)a) | (((ticks)d) << 32));
528 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
529 struct ArrayObject * chararray=VAR(___s___)->___value___;
531 int offset=VAR(___s___)->___offset___;
532 for(i=0; i<VAR(___s___)->___count___; i++) {
533 short sc=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
542 #ifdef D___RecoveryStat______printRecoveryStat____
544 void CALL00(___RecoveryStat______printRecoveryStat____) {
548 void CALL00(___RecoveryStat______printRecoveryStat____) {
556 void CALL00(___System______clearPrefetchCache____) {
561 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
562 /* Manual Prefetches to be inserted */
563 //printf("DEBUG-> %s() ___Object___ * ___o___ = %x\n", __func__, VAR(___o___));
564 //printf("DEBUG-> %s() ArrayObject * = %x\n", __func__, VAR(___offsets___));
565 int numoffset=VAR(___offsets___)->___length___;
567 short offArry[numoffset+2];
570 for(i = 2; i<(numoffset+2); i++) {
571 offArry[i] = *((short *)(((char *)&VAR(___offsets___)->___length___) + sizeof(int) + (i-2) * sizeof(short)));
572 //printf("DEBUG-> offArry[%d] = %d\n", i, offArry[i]);
575 if(((unsigned int)(VAR(___o___)) & 1) != 0) { //odd
576 oid = (unsigned int) VAR(___o___); //outside transaction therefore just an oid
578 oid = (unsigned int) COMPOID(VAR(___o___)); //inside transaction therefore a pointer to oid
580 rangePrefetch(oid, (short)(numoffset+2), offArry);
583 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
588 #ifdef D___Task______execution____
589 extern void* virtualtable[];
590 // associated with Task.execution(). finds proper execute method and call it
591 void CALL01(___Task______execution____,struct ___Task___ * ___this___)
594 oid = (unsigned int) VAR(___this___); // object id
595 int type = getObjType(oid); // object type
598 int p[] = {1,0 , oid};
599 ((void(*) (void *))virtualtable[type*MAXCOUNT + EXECUTEMETHOD])(p);
601 // call the proper execute method
602 ((void(*) (void *))virtualtable[type*MAXCOUNT + EXECUTEMETHOD])(oid);
609 /* STM Barrier constructs */
610 #ifdef D___Barrier______setBarrier____I
611 void CALL11(___Barrier______setBarrier____I, int nthreads, int nthreads) {
612 // Barrier initialization
614 if((ret = pthread_barrier_init(&barrier, NULL, nthreads)) != 0) {
615 printf("%s() Could not create a barrier: numthreads = 0 in %s\n", __func__, __FILE__);
621 #ifdef D___Barrier______enterBarrier____
622 void CALL00(___Barrier______enterBarrier____) {
623 // Synchronization point
626 EVLOGEVENT(EV_ENTERBARRIER);
629 stopforgc((struct garbagelist *)___params___);
631 ret = pthread_barrier_wait(&barrier);
635 if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
636 printf("%s() Could not wait on barrier: error %d in %s\n", __func__, errno, __FILE__);
640 EVLOGEVENT(EV_EXITBARRIER);
645 /* Object allocation function */
648 __attribute__((malloc)) void * allocate_newglobal(int type) {
649 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(classsize[type]);
651 //printf("DEBUG %s(), type= %x\n", __func__, type);
660 /* Array allocation function */
662 __attribute__((malloc)) struct ArrayObject * allocate_newarrayglobal(int type, int length) {
663 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(sizeof(struct ArrayObject)+length*classsize[type]);
665 printf("ERROR: negative array\n");
669 v->___length___=length;
681 // STM Versions of allocation functions
683 /* Object allocation function */
684 __attribute__((malloc)) void * allocate_newtrans(void * ptr, int type) {
686 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type], 0);
688 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type]);
692 v->___objlocation___=v;
696 /* Array allocation function */
697 __attribute__((malloc)) struct ArrayObject * allocate_newarraytrans(void * ptr, int type, int length) {
699 int basesize=length*classsize[type];
700 //round the base size up
701 basesize=(basesize+LOWMASK)&HIGHMASK;
702 int numlocks=basesize>>INDEXSHIFT;
703 int bookkeepsize=numlocks*2*sizeof(int);
704 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+basesize+bookkeepsize, bookkeepsize);
705 unsigned int *intptr=(unsigned int *)(((char *)v)-sizeof(objheader_t));
706 for(;numlocks>0;numlocks--) {
711 v->lowindex=MAXARRAYSIZE;
713 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]);
717 printf("ERROR: negative array\n");
720 v->___objlocation___=(struct ___Object___*)v;
722 v->___length___=length;
726 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
727 objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, classsize[type]+sizeof(objheader_t));
728 struct ___Object___ * v=(struct ___Object___ *) &tmp[1];
730 initdsmlocks(&tmp->lock);
732 v->___objlocation___=v;
737 /* Array allocation function */
739 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
741 int basesize=length*classsize[type];
742 //round the base size up
743 basesize=(basesize+LOWMASK)&HIGHMASK;
744 int numlocks=basesize>>INDEXSHIFT;
745 int bookkeepsize=(numlocks)*2*sizeof(int);
746 int *tmpint=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+basesize+sizeof(objheader_t)+bookkeepsize);
747 for(;numlocks>0;numlocks--) {
751 objheader_t *tmp=(objheader_t *)tmpint;
752 struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
754 v->lowindex=MAXARRAYSIZE;
756 objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t));
757 struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
760 tmp->lock=RW_LOCK_BIAS;
762 initdsmlocks(&tmp->lock);
768 printf("ERROR: negative array %d\n", length);
771 v->___objlocation___=(struct ___Object___ *)v;
772 v->___length___=length;
778 #if defined(PRECISE_GC)
780 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
781 return allocate_new_mlp(ptr, type, 0, 0);
783 __attribute__((malloc)) void * allocate_new_mlp(void * ptr, int type, int oid, int allocsite) {
785 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
787 struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
799 v->allocsite=allocsite;
804 /* Array allocation function */
806 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
807 return allocate_newarray_mlp(ptr, type, length, 0, 0);
809 __attribute__((malloc)) struct ArrayObject * allocate_newarray_mlp(void * ptr, int type, int length, int oid, int allocsite) {
811 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
813 struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
816 printf("ERROR: negative array\n");
819 v->___length___=length;
830 v->allocsite=allocsite;
836 __attribute__((malloc)) void * allocate_new(int type) {
837 struct ___Object___ * v=FREEMALLOC(classsize[type]);
845 /* Array allocation function */
847 __attribute__((malloc)) struct ArrayObject * allocate_newarray(int type, int length) {
848 __attribute__((malloc)) struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
850 v->___length___=length;
859 /* Converts C character arrays into Java strings */
861 __attribute__((malloc)) struct ___String___ * NewStringShort(void * ptr, const short *str,int length) {
863 __attribute__((malloc)) struct ___String___ * NewStringShort(const short *str,int length) {
867 struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
868 INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
869 struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
870 chararray=(struct ArrayObject *) ptrarray[2];
872 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
873 struct ___String___ * strobj=allocate_new(STRINGTYPE);
875 strobj->___value___=chararray;
876 strobj->___count___=length;
877 strobj->___offset___=0;
879 for(i=0; i<length; i++) {
880 ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=str[i];
885 /* Converts C character arrays into Java strings */
887 __attribute__((malloc)) struct ___String___ * NewString(void * ptr, const char *str,int length) {
889 __attribute__((malloc)) struct ___String___ * NewString(const char *str,int length) {
893 struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
894 INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
895 struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
896 chararray=(struct ArrayObject *) ptrarray[2];
898 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
899 struct ___String___ * strobj=allocate_new(STRINGTYPE);
901 strobj->___value___=chararray;
902 strobj->___count___=length;
903 strobj->___offset___=0;
905 for(i=0; i<length; i++) {
906 ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=(short)str[i];
911 /* Generated code calls this if we fail a bounds check */
913 void failedboundschk(int num) {
915 printf("Array out of bounds\n");
922 longjmp(error_handler,2);
926 /* Abort task call */
929 longjmp(error_handler,4);
931 printf("Aborting\n");
937 #ifdef D___System______Assert____Z
938 void CALL11(___System______Assert____Z, int ___status___, int ___status___) {
940 printf("Assertion violation\n");
941 *((int *)(NULL)); //force stack trace error