2 #include "structdefs.h"
9 #include "methodheaders.h"
11 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
17 #include "DSTM/interface_recovery/dstm.h"
18 #include "DSTM/interface_recovery/altprelookup.h"
21 extern int numRecovery;
22 extern unsigned int deadMachine[8];
23 extern unsigned int sizeOfRedupedData[8];
24 extern double elapsedTime[8];
28 #include "DSTM/interface/dstm.h"
29 #include "DSTM/interface/altprelookup.h"
30 #include "DSTM/interface/prefetch.h"
38 #define ARRAY_LENGTH 700003
40 __thread int event[ARRAY_LENGTH];
41 __thread unsigned long long clkticks[ARRAY_LENGTH];
42 unsigned long long beginClock=0;
43 #define FILENAME "log"
47 __thread int objcount=0;
48 #define ASSIGNUID(x) { \
49 int number=((objcount++)<<EVTHREADSHIFT)|threadnum; \
56 #if defined(THREADS)||defined(STM)
57 /* Global barrier for STM */
58 pthread_barrier_t barrier;
59 pthread_barrierattr_t attr;
67 #define GCPOINT(x) ((INTPTR)((x)*0.99))
70 extern int classsize[];
71 extern int typearray[];
72 extern int typearray2[];
73 jmp_buf error_handler;
78 float failurechance=0;
81 int injectinstructionfailures;
83 float instfailurechance=0;
86 typedef unsigned long long ticks;
91 int instanceof(struct ___Object___ *ptr, int type) {
103 i=typearray2[i-NUMCLASSES];
109 void exithandler(int sig, siginfo_t *info, void * uap) {
113 void initializeexithandler() {
114 struct sigaction sig;
115 sig.sa_sigaction=&exithandler;
116 sig.sa_flags=SA_SIGINFO;
117 sigemptyset(&sig.sa_mask);
118 sigaction(SIGUSR2, &sig, 0);
122 /* This function inject failures */
124 void injectinstructionfailure() {
126 if (injectinstructionfailures) {
129 instructioncount=failurecount;
130 instaccum+=failurecount;
131 if ((((double)random())/RAND_MAX)<instfailurechance) {
134 printf("FAILURE!!! %d\n",numfailures);
135 longjmp(error_handler,11);
140 if (injectinstructionfailures) {
143 instaccum+=failurecount;
144 if ((((double)random())/RAND_MAX)<instfailurechance) {
147 printf("FAILURE!!! %d\n",numfailures);
155 #ifdef D___Double______nativeparsedouble____L___String___
156 double CALL01(___Double______nativeparsedouble____L___String___,struct ___String___ * ___str___) {
157 int length=VAR(___str___)->___count___;
158 int maxlength=(length>60)?60:length;
159 char str[maxlength+1];
160 struct ArrayObject * chararray=VAR(___str___)->___value___;
162 int offset=VAR(___str___)->___offset___;
163 for(i=0; i<maxlength; i++) {
164 str[i]=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
172 #ifdef D___Double______nativeparsedouble_____AR_B_I_I
173 double CALL23(___Double______nativeparsedouble_____AR_B_I_I, int start, int length,int start,int length,struct ArrayObject * ___str___) {
174 int maxlength=(length>60)?60:length;
175 char str[maxlength+1];
176 struct ArrayObject * bytearray=VAR(___str___);
178 for(i=0; i<maxlength; i++) {
179 str[i]=(((char *)&bytearray->___length___)+sizeof(int))[i+start];
187 #ifdef D___Double______doubleToRawLongBits____D
199 long long CALL11(___Double______doubleToRawLongBits____D, double dval, double dval) {
203 #if defined(__IEEE_BYTES_LITTLE_ENDIAN)
204 /* On little endian ARM processors when using FPA, word order of
205 doubles is still big endian. So take that into account here. When
206 using VFP, word order of doubles follows byte order. */
208 #define SWAP_DOUBLE(a) (((a) << 32) | (((a) >> 32) & 0x00000000ffffffff))
210 val.j = SWAP_DOUBLE(val.j);
217 #ifdef D___Double______longBitsToDouble____J
218 double CALL11(___Double______longBitsToDouble____J, long long lval, long long lval) {
222 #if defined(__IEEE_BYTES_LITTLE_ENDIAN)
224 #define SWAP_DOUBLE(a) (((a) << 32) | (((a) >> 32) & 0x00000000ffffffff))
226 val.j = SWAP_DOUBLE(val.j);
233 #ifdef D___String______convertdoubletochar____D__AR_C
234 int CALL12(___String______convertdoubletochar____D__AR_C, double ___val___, double ___val___, struct ArrayObject ___chararray___) {
235 int length=VAR(___chararray___)->___length___;
238 int num=snprintf(str, length, "%f",___val___);
241 for(i=0; i<length; i++) {
242 ((short *)(((char *)&VAR(___chararray___)->___length___)+sizeof(int)))[i]=(short)str[i];
247 #ifdef D___System______deepArrayCopy____L___Object____L___Object___
248 void deepArrayCopy(struct ___Object___ * dst, struct ___Object___ * src) {
249 int dsttype=((int *)dst)[0];
250 int srctype=((int *)src)[0];
252 src=src->___objlocation___;
254 if (dsttype<NUMCLASSES||srctype<NUMCLASSES||srctype!=dsttype)
256 struct ArrayObject *aodst=(struct ArrayObject *)dst;
257 struct ArrayObject *aosrc=(struct ArrayObject *)src;
258 int dstlength=aodst->___length___;
259 int srclength=aosrc->___length___;
260 if (dstlength!=srclength)
262 unsigned INTPTR *pointer=pointerarray[srctype];
264 int elementsize=classsize[srctype];
265 int size=srclength*elementsize;
267 memcpy(((char *)&aodst->___length___)+sizeof(int) , ((char *)&aosrc->___length___)+sizeof(int), size);
271 for(i=0;i<srclength;i++) {
272 struct ___Object___ * ptr=((struct ___Object___**)(((char*) &aosrc->___length___)+sizeof(int)))[i];
273 int ptrtype=((int *)ptr)[0];
274 if (ptrtype>=NUMCLASSES) {
275 struct ___Object___ * dstptr=((struct ___Object___**)(((char*) &aodst->___length___)+sizeof(int)))[i];
276 deepArrayCopy(dstptr,ptr);
279 ((struct ___Object___ **)(((char*) &aodst->___length___)+sizeof(int)))[i]=ptr;
285 void CALL02(___System______deepArrayCopy____L___Object____L___Object___, struct ___Object___ * ___dst___, struct ___Object___ * ___src___) {
286 deepArrayCopy(VAR(___dst___), VAR(___src___));
290 #ifdef D___System______arraycopy____L___Object____I_L___Object____I_I
291 void arraycopy(struct ___Object___ *src, int srcPos, struct ___Object___ *dst, int destPos, int length) {
292 int dsttype=((int *)dst)[0];
293 int srctype=((int *)src)[0];
295 //not an array or type mismatch
296 if (dsttype<NUMCLASSES||srctype<NUMCLASSES)
298 if (srctype!=dsttype)
299 printf("Potential type mismatch in arraycopy\n");
301 struct ArrayObject *aodst=(struct ArrayObject *)dst;
302 struct ArrayObject *aosrc=(struct ArrayObject *)src;
303 int dstlength=aodst->___length___;
304 int srclength=aosrc->___length___;
308 if (srcPos+length>srclength)
310 if (destPos+length>dstlength)
313 unsigned INTPTR *pointer=pointerarray[srctype];
315 int elementsize=classsize[srctype];
316 int size=length*elementsize;
318 memcpy(((char *)&aodst->___length___)+sizeof(int)+destPos*elementsize, ((char *)&aosrc->___length___)+sizeof(int)+srcPos*elementsize, size);
322 for(i=0;i<length;i++) {
323 struct ___Object___ * ptr=((struct ___Object___**)(((char*) &aosrc->___length___)+sizeof(int)))[i+srcPos];
325 ((struct ___Object___ **)(((char*) &aodst->___length___)+sizeof(int)))[i+destPos]=ptr;
330 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___) {
331 arraycopy(VAR(___src___), ___srcPos___, VAR(___dst___), ___destPos___, ___length___);
335 #ifdef D___Runtime______availableProcessors____
336 int CALL01(___Runtime______availableProcessors____, struct ___Runtime___ * ___this___) {
337 printf("Unimplemented Runtime.availableProcessors\n");
342 #ifdef D___Runtime______freeMemory____
343 long long CALL01(___Runtime______freeMemory____, struct ___Runtime___ * ___this___) {
344 printf("Unimplemented Runtime.freeMemory\n");
345 return 1024*1024*1024;
349 #ifdef D___Runtime______totalMemory____
350 long long CALL01(___Runtime______totalMemory____, struct ___Runtime___ * ___this___) {
351 printf("Unimplemented Runtime.totalMemory\n");
352 return 1024*1024*1024;
356 #ifdef D___Runtime______maxMemory____
357 long long CALL01(___Runtime______maxMemory____, struct ___Runtime___ * ___this___) {
358 printf("Unimplemented Runtime.maxMemory\n");
359 return 1024*1024*1024;
363 void CALL11(___System______exit____I,int ___status___, int ___status___) {
366 printf("numTransCommit = %d\n", numTransCommit);
367 printf("numTransAbort = %d\n", numTransAbort);
368 printf("nSoftAbort = %d\n", nSoftAbort);
371 printf("nSoftAbortCommit = %d\n", nSoftAbortCommit);
372 printf("nSoftAbortAbort = %d\n", nSoftAbortAbort);
375 for(i=0; i<TOTALNUMCLASSANDARRAY; i++) {
376 printf("typesCausingAbort[%2d] numaccess= %5d numabort= %3d\n", i, typesCausingAbort[i].numaccess, typesCausingAbort[i].numabort);
387 void CALL11(___System______logevent____I,int ___event___, int ___event___) {
389 event[counter] = ___event___;
390 clkticks[counter] = rdtsc();
396 void CALL00(___System______logevent____) {
403 void CALL11(___System______flushToFile____I, int ___threadid___, int ___threadid___) {
408 memset(filename, 0, 20);
409 sprintf(filename, "%s_%d", FILENAME, ___threadid___);
410 if ((fp = fopen(filename, "w+")) == NULL) {
415 for (i = 0; i < counter-1; i++) {
416 fprintf(fp, "%d %lld %lld\n", event[i], clkticks[i]-beginClock, clkticks[i+1]-beginClock);
418 fprintf(fp, "%d %lld\n", event[i], clkticks[i]-beginClock);
425 void CALL00(___System______initLog____) {
429 for(i=0; i<ARRAY_LENGTH; i++) {
438 #ifdef D___Vector______removeElement_____AR_L___Object____I_I
439 void CALL23(___Vector______removeElement_____AR_L___Object____I_I, int ___index___, int ___size___, struct ArrayObject * ___array___, int ___index___, int ___size___) {
440 char* offset=((char *)(&VAR(___array___)->___length___))+sizeof(unsigned int)+sizeof(void *)*___index___;
441 memmove(offset, offset+sizeof(void *),(___size___-___index___-1)*sizeof(void *));
445 void CALL11(___System______printI____I,int ___status___, int ___status___) {
446 printf("%d\n",___status___);
449 long long CALL00(___System______currentTimeMillis____) {
450 struct timeval tv; long long retval;
451 gettimeofday(&tv, NULL);
452 retval = tv.tv_sec; /* seconds */
453 retval*=1000; /* milliseconds */
454 retval+= (tv.tv_usec/1000); /* adjust milliseconds & add them in */
458 #ifdef D___System______gc____
459 void CALL00(___System______gc____) {
460 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
461 while (pthread_mutex_trylock(&gclock)!=0) {
462 stopforgc((struct garbagelist *)___params___);
467 /* Grow the to heap if necessary */
469 INTPTR curr_heapsize=curr_heaptop-curr_heapbase;
470 INTPTR to_heapsize=to_heaptop-to_heapbase;
472 if (curr_heapsize>to_heapsize) {
474 to_heapbase=malloc(curr_heapsize);
475 if (to_heapbase==NULL) {
476 printf("Error Allocating enough memory\n");
479 to_heaptop=to_heapbase+curr_heapsize;
480 to_heapptr=to_heapbase;
485 collect((struct garbagelist *)___params___);
488 void * tmp=to_heapbase;
489 to_heapbase=curr_heapbase;
493 to_heaptop=curr_heaptop;
497 curr_heapptr=to_heapptr;
498 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
499 to_heapptr=to_heapbase;
500 bzero(tmp, curr_heaptop-tmp);
504 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
505 pthread_mutex_unlock(&gclock);
510 long long CALL00(___System______microTimes____) {
513 gettimeofday(&tv, NULL);
514 retval = tv.tv_sec; /* seconds */
515 retval*=1000000; /* microsecs */
516 retval+= (tv.tv_usec); /* adjust microseconds & add them in */
520 long long CALL00(___System______getticks____) {
523 asm volatile("rdtsc" : "=a" (a), "=d" (d));
524 return (((ticks)a) | (((ticks)d) << 32));
527 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
528 struct ArrayObject * chararray=VAR(___s___)->___value___;
530 int offset=VAR(___s___)->___offset___;
531 for(i=0; i<VAR(___s___)->___count___; i++) {
532 short sc=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
541 #ifdef D___RecoveryStat______printRecoveryStat____
543 void CALL00(___RecoveryStat______printRecoveryStat____) {
547 void CALL00(___RecoveryStat______printRecoveryStat____) {
555 void CALL00(___System______clearPrefetchCache____) {
560 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
561 /* Manual Prefetches to be inserted */
562 //printf("DEBUG-> %s() ___Object___ * ___o___ = %x\n", __func__, VAR(___o___));
563 //printf("DEBUG-> %s() ArrayObject * = %x\n", __func__, VAR(___offsets___));
564 int numoffset=VAR(___offsets___)->___length___;
566 short offArry[numoffset+2];
569 for(i = 2; i<(numoffset+2); i++) {
570 offArry[i] = *((short *)(((char *)&VAR(___offsets___)->___length___) + sizeof(int) + (i-2) * sizeof(short)));
571 //printf("DEBUG-> offArry[%d] = %d\n", i, offArry[i]);
574 if(((unsigned int)(VAR(___o___)) & 1) != 0) { //odd
575 oid = (unsigned int) VAR(___o___); //outside transaction therefore just an oid
577 oid = (unsigned int) COMPOID(VAR(___o___)); //inside transaction therefore a pointer to oid
579 rangePrefetch(oid, (short)(numoffset+2), offArry);
582 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
587 #ifdef D___Task______execution____
588 extern void* virtualtable[];
589 // associated with Task.execution(). finds proper execute method and call it
590 void CALL01(___Task______execution____,struct ___Task___ * ___this___)
593 oid = (unsigned int) VAR(___this___); // object id
594 int type = getObjType(oid); // object type
597 int p[] = {1,0 , oid};
598 ((void(*) (void *))virtualtable[type*MAXCOUNT + EXECUTEMETHOD])(p);
600 // call the proper execute method
601 ((void(*) (void *))virtualtable[type*MAXCOUNT + EXECUTEMETHOD])(oid);
608 /* STM Barrier constructs */
609 #ifdef D___Barrier______setBarrier____I
610 void CALL11(___Barrier______setBarrier____I, int nthreads, int nthreads) {
611 // Barrier initialization
613 if((ret = pthread_barrier_init(&barrier, NULL, nthreads)) != 0) {
614 printf("%s() Could not create a barrier: numthreads = 0 in %s\n", __func__, __FILE__);
620 #ifdef D___Barrier______enterBarrier____
621 void CALL00(___Barrier______enterBarrier____) {
622 // Synchronization point
625 EVLOGEVENT(EV_ENTERBARRIER);
628 stopforgc((struct garbagelist *)___params___);
630 ret = pthread_barrier_wait(&barrier);
634 if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
635 printf("%s() Could not wait on barrier: error %d in %s\n", __func__, errno, __FILE__);
639 EVLOGEVENT(EV_EXITBARRIER);
644 /* Object allocation function */
647 __attribute__((malloc)) void * allocate_newglobal(int type) {
648 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(classsize[type]);
650 //printf("DEBUG %s(), type= %x\n", __func__, type);
659 /* Array allocation function */
661 __attribute__((malloc)) struct ArrayObject * allocate_newarrayglobal(int type, int length) {
662 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(sizeof(struct ArrayObject)+length*classsize[type]);
664 printf("ERROR: negative array\n");
668 v->___length___=length;
680 // STM Versions of allocation functions
682 /* Object allocation function */
683 __attribute__((malloc)) void * allocate_newtrans(void * ptr, int type) {
685 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type], 0);
687 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type]);
691 v->___objlocation___=v;
695 /* Array allocation function */
696 __attribute__((malloc)) struct ArrayObject * allocate_newarraytrans(void * ptr, int type, int length) {
698 int basesize=length*classsize[type];
699 //round the base size up
700 basesize=(basesize+LOWMASK)&HIGHMASK;
701 int numlocks=basesize>>INDEXSHIFT;
702 int bookkeepsize=numlocks*2*sizeof(int);
703 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+basesize+bookkeepsize, bookkeepsize);
704 unsigned int *intptr=(unsigned int *)(((char *)v)-sizeof(objheader_t));
705 for(;numlocks>0;numlocks--) {
710 v->lowindex=MAXARRAYSIZE;
712 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]);
716 printf("ERROR: negative array\n");
719 v->___objlocation___=(struct ___Object___*)v;
721 v->___length___=length;
725 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
726 objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, classsize[type]+sizeof(objheader_t));
727 struct ___Object___ * v=(struct ___Object___ *) &tmp[1];
729 initdsmlocks(&tmp->lock);
731 v->___objlocation___=v;
736 /* Array allocation function */
738 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
740 int basesize=length*classsize[type];
741 //round the base size up
742 basesize=(basesize+LOWMASK)&HIGHMASK;
743 int numlocks=basesize>>INDEXSHIFT;
744 int bookkeepsize=(numlocks)*2*sizeof(int);
745 int *tmpint=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+basesize+sizeof(objheader_t)+bookkeepsize);
746 for(;numlocks>0;numlocks--) {
750 objheader_t *tmp=(objheader_t *)tmpint;
751 struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
753 v->lowindex=MAXARRAYSIZE;
755 objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t));
756 struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
759 tmp->lock=RW_LOCK_BIAS;
761 initdsmlocks(&tmp->lock);
767 printf("ERROR: negative array %d\n", length);
770 v->___objlocation___=(struct ___Object___ *)v;
771 v->___length___=length;
777 #if defined(PRECISE_GC)
779 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
780 return allocate_new_mlp(ptr, type, 0, 0);
782 __attribute__((malloc)) void * allocate_new_mlp(void * ptr, int type, int oid, int allocsite) {
784 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
786 struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
798 v->allocsite=allocsite;
803 /* Array allocation function */
805 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
806 return allocate_newarray_mlp(ptr, type, length, 0, 0);
808 __attribute__((malloc)) struct ArrayObject * allocate_newarray_mlp(void * ptr, int type, int length, int oid, int allocsite) {
810 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
812 struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
815 printf("ERROR: negative array\n");
818 v->___length___=length;
829 v->allocsite=allocsite;
835 __attribute__((malloc)) void * allocate_new(int type) {
836 struct ___Object___ * v=FREEMALLOC(classsize[type]);
844 /* Array allocation function */
846 __attribute__((malloc)) struct ArrayObject * allocate_newarray(int type, int length) {
847 __attribute__((malloc)) struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
849 v->___length___=length;
858 /* Converts C character arrays into Java strings */
860 __attribute__((malloc)) struct ___String___ * NewStringShort(void * ptr, const short *str,int length) {
862 __attribute__((malloc)) struct ___String___ * NewStringShort(const short *str,int length) {
866 struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
867 INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
868 struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
869 chararray=(struct ArrayObject *) ptrarray[2];
871 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
872 struct ___String___ * strobj=allocate_new(STRINGTYPE);
874 strobj->___value___=chararray;
875 strobj->___count___=length;
876 strobj->___offset___=0;
878 for(i=0; i<length; i++) {
879 ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=str[i];
884 /* Converts C character arrays into Java strings */
886 __attribute__((malloc)) struct ___String___ * NewString(void * ptr, const char *str,int length) {
888 __attribute__((malloc)) struct ___String___ * NewString(const char *str,int length) {
892 struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
893 INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
894 struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
895 chararray=(struct ArrayObject *) ptrarray[2];
897 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
898 struct ___String___ * strobj=allocate_new(STRINGTYPE);
900 strobj->___value___=chararray;
901 strobj->___count___=length;
902 strobj->___offset___=0;
904 for(i=0; i<length; i++) {
905 ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=(short)str[i];
910 /* Generated code calls this if we fail a bounds check */
912 void failedboundschk(int num) {
914 printf("Array out of bounds\n");
921 longjmp(error_handler,2);
925 /* Abort task call */
928 longjmp(error_handler,4);
930 printf("Aborting\n");
936 #ifdef D___System______Assert____Z
937 void CALL11(___System______Assert____Z, int ___status___, int ___status___) {
939 printf("Assertion violation\n");
940 *((int *)(NULL)); //force stack trace error