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||srctype!=dsttype)
299 struct ArrayObject *aodst=(struct ArrayObject *)dst;
300 struct ArrayObject *aosrc=(struct ArrayObject *)src;
301 int dstlength=aodst->___length___;
302 int srclength=aosrc->___length___;
306 if (srcPos+length>srclength)
308 if (destPos+length>dstlength)
311 unsigned INTPTR *pointer=pointerarray[srctype];
313 int elementsize=classsize[srctype];
314 int size=length*elementsize;
316 memcpy(((char *)&aodst->___length___)+sizeof(int)+destPos*elementsize, ((char *)&aosrc->___length___)+sizeof(int)+srcPos*elementsize, size);
320 for(i=0;i<length;i++) {
321 struct ___Object___ * ptr=((struct ___Object___**)(((char*) &aosrc->___length___)+sizeof(int)))[i+srcPos];
322 int ptrtype=((int *)ptr)[0];
324 ((struct ___Object___ **)(((char*) &aodst->___length___)+sizeof(int)))[i+destPos]=ptr;
329 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___) {
330 arraycopy(VAR(___src___), ___srcPos___, VAR(___dst___), ___destPos___, ___length___);
334 #ifdef D___Runtime______availableProcessors____
335 int CALL01(___Runtime______availableProcessors____, struct ___Runtime___ * ___this___) {
336 printf("Unimplemented Runtime.availableProcessors\n");
341 #ifdef D___Runtime______freeMemory____
342 long long CALL01(___Runtime______freeMemory____, struct ___Runtime___ * ___this___) {
343 printf("Unimplemented Runtime.freeMemory\n");
344 return 1024*1024*1024;
348 #ifdef D___Runtime______totalMemory____
349 long long CALL01(___Runtime______totalMemory____, struct ___Runtime___ * ___this___) {
350 printf("Unimplemented Runtime.totalMemory\n");
351 return 1024*1024*1024;
355 #ifdef D___Runtime______maxMemory____
356 long long CALL01(___Runtime______maxMemory____, struct ___Runtime___ * ___this___) {
357 printf("Unimplemented Runtime.maxMemory\n");
358 return 1024*1024*1024;
362 void CALL11(___System______exit____I,int ___status___, int ___status___) {
365 printf("numTransCommit = %d\n", numTransCommit);
366 printf("numTransAbort = %d\n", numTransAbort);
367 printf("nSoftAbort = %d\n", nSoftAbort);
370 printf("nSoftAbortCommit = %d\n", nSoftAbortCommit);
371 printf("nSoftAbortAbort = %d\n", nSoftAbortAbort);
374 for(i=0; i<TOTALNUMCLASSANDARRAY; i++) {
375 printf("typesCausingAbort[%2d] numaccess= %5d numabort= %3d\n", i, typesCausingAbort[i].numaccess, typesCausingAbort[i].numabort);
386 void CALL11(___System______logevent____I,int ___event___, int ___event___) {
388 event[counter] = ___event___;
389 clkticks[counter] = rdtsc();
395 void CALL00(___System______logevent____) {
402 void CALL11(___System______flushToFile____I, int ___threadid___, int ___threadid___) {
407 memset(filename, 0, 20);
408 sprintf(filename, "%s_%d", FILENAME, ___threadid___);
409 if ((fp = fopen(filename, "w+")) == NULL) {
414 for (i = 0; i < counter-1; i++) {
415 fprintf(fp, "%d %lld %lld\n", event[i], clkticks[i]-beginClock, clkticks[i+1]-beginClock);
417 fprintf(fp, "%d %lld\n", event[i], clkticks[i]-beginClock);
424 void CALL00(___System______initLog____) {
428 for(i=0; i<ARRAY_LENGTH; i++) {
437 #ifdef D___Vector______removeElement_____AR_L___Object____I_I
438 void CALL23(___Vector______removeElement_____AR_L___Object____I_I, int ___index___, int ___size___, struct ArrayObject * ___array___, int ___index___, int ___size___) {
439 char* offset=((char *)(&VAR(___array___)->___length___))+sizeof(unsigned int)+sizeof(void *)*___index___;
440 memmove(offset, offset+sizeof(void *),(___size___-___index___-1)*sizeof(void *));
444 void CALL11(___System______printI____I,int ___status___, int ___status___) {
445 printf("%d\n",___status___);
448 long long CALL00(___System______currentTimeMillis____) {
449 struct timeval tv; long long retval;
450 gettimeofday(&tv, NULL);
451 retval = tv.tv_sec; /* seconds */
452 retval*=1000; /* milliseconds */
453 retval+= (tv.tv_usec/1000); /* adjust milliseconds & add them in */
457 #ifdef D___System______gc____
458 void CALL00(___System______gc____) {
459 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
460 while (pthread_mutex_trylock(&gclock)!=0) {
461 stopforgc((struct garbagelist *)___params___);
466 /* Grow the to heap if necessary */
468 INTPTR curr_heapsize=curr_heaptop-curr_heapbase;
469 INTPTR to_heapsize=to_heaptop-to_heapbase;
471 if (curr_heapsize>to_heapsize) {
473 to_heapbase=malloc(curr_heapsize);
474 if (to_heapbase==NULL) {
475 printf("Error Allocating enough memory\n");
478 to_heaptop=to_heapbase+curr_heapsize;
479 to_heapptr=to_heapbase;
484 collect((struct garbagelist *)___params___);
487 void * tmp=to_heapbase;
488 to_heapbase=curr_heapbase;
492 to_heaptop=curr_heaptop;
496 curr_heapptr=to_heapptr;
497 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
498 to_heapptr=to_heapbase;
499 bzero(tmp, curr_heaptop-tmp);
503 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
504 pthread_mutex_unlock(&gclock);
509 long long CALL00(___System______microTimes____) {
512 gettimeofday(&tv, NULL);
513 retval = tv.tv_sec; /* seconds */
514 retval*=1000000; /* microsecs */
515 retval+= (tv.tv_usec); /* adjust microseconds & add them in */
519 long long CALL00(___System______getticks____) {
522 asm volatile("rdtsc" : "=a" (a), "=d" (d));
523 return (((ticks)a) | (((ticks)d) << 32));
526 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
527 struct ArrayObject * chararray=VAR(___s___)->___value___;
529 int offset=VAR(___s___)->___offset___;
530 for(i=0; i<VAR(___s___)->___count___; i++) {
531 short sc=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
540 #ifdef D___RecoveryStat______printRecoveryStat____
542 void CALL00(___RecoveryStat______printRecoveryStat____) {
546 void CALL00(___RecoveryStat______printRecoveryStat____) {
554 void CALL00(___System______clearPrefetchCache____) {
559 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
560 /* Manual Prefetches to be inserted */
561 //printf("DEBUG-> %s() ___Object___ * ___o___ = %x\n", __func__, VAR(___o___));
562 //printf("DEBUG-> %s() ArrayObject * = %x\n", __func__, VAR(___offsets___));
563 int numoffset=VAR(___offsets___)->___length___;
565 short offArry[numoffset+2];
568 for(i = 2; i<(numoffset+2); i++) {
569 offArry[i] = *((short *)(((char *)&VAR(___offsets___)->___length___) + sizeof(int) + (i-2) * sizeof(short)));
570 //printf("DEBUG-> offArry[%d] = %d\n", i, offArry[i]);
573 if(((unsigned int)(VAR(___o___)) & 1) != 0) { //odd
574 oid = (unsigned int) VAR(___o___); //outside transaction therefore just an oid
576 oid = (unsigned int) COMPOID(VAR(___o___)); //inside transaction therefore a pointer to oid
578 rangePrefetch(oid, (short)(numoffset+2), offArry);
581 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
586 #ifdef D___Task______execution____
587 extern void* virtualtable[];
588 // associated with Task.execution(). finds proper execute method and call it
589 void CALL01(___Task______execution____,struct ___Task___ * ___this___)
592 oid = (unsigned int) VAR(___this___); // object id
593 int type = getObjType(oid); // object type
596 int p[] = {1,0 , oid};
597 ((void(*) (void *))virtualtable[type*MAXCOUNT + EXECUTEMETHOD])(p);
599 // call the proper execute method
600 ((void(*) (void *))virtualtable[type*MAXCOUNT + EXECUTEMETHOD])(oid);
607 /* STM Barrier constructs */
608 #ifdef D___Barrier______setBarrier____I
609 void CALL11(___Barrier______setBarrier____I, int nthreads, int nthreads) {
610 // Barrier initialization
612 if((ret = pthread_barrier_init(&barrier, NULL, nthreads)) != 0) {
613 printf("%s() Could not create a barrier: numthreads = 0 in %s\n", __func__, __FILE__);
619 #ifdef D___Barrier______enterBarrier____
620 void CALL00(___Barrier______enterBarrier____) {
621 // Synchronization point
624 EVLOGEVENT(EV_ENTERBARRIER);
627 stopforgc((struct garbagelist *)___params___);
629 ret = pthread_barrier_wait(&barrier);
633 if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
634 printf("%s() Could not wait on barrier: error %d in %s\n", __func__, errno, __FILE__);
638 EVLOGEVENT(EV_EXITBARRIER);
643 /* Object allocation function */
646 __attribute__((malloc)) void * allocate_newglobal(int type) {
647 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(classsize[type]);
649 //printf("DEBUG %s(), type= %x\n", __func__, type);
658 /* Array allocation function */
660 __attribute__((malloc)) struct ArrayObject * allocate_newarrayglobal(int type, int length) {
661 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(sizeof(struct ArrayObject)+length*classsize[type]);
663 printf("ERROR: negative array\n");
667 v->___length___=length;
679 // STM Versions of allocation functions
681 /* Object allocation function */
682 __attribute__((malloc)) void * allocate_newtrans(void * ptr, int type) {
684 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type], 0);
686 struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type]);
690 v->___objlocation___=v;
694 /* Array allocation function */
695 __attribute__((malloc)) struct ArrayObject * allocate_newarraytrans(void * ptr, int type, int length) {
697 int basesize=length*classsize[type];
698 //round the base size up
699 basesize=(basesize+LOWMASK)&HIGHMASK;
700 int numlocks=basesize>>INDEXSHIFT;
701 int bookkeepsize=numlocks*2*sizeof(int);
702 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+basesize+bookkeepsize, bookkeepsize);
703 unsigned int *intptr=(unsigned int *)(((char *)v)-sizeof(objheader_t));
704 for(;numlocks>0;numlocks--) {
709 v->lowindex=MAXARRAYSIZE;
711 struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]);
715 printf("ERROR: negative array\n");
718 v->___objlocation___=(struct ___Object___*)v;
720 v->___length___=length;
724 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
725 objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, classsize[type]+sizeof(objheader_t));
726 struct ___Object___ * v=(struct ___Object___ *) &tmp[1];
728 initdsmlocks(&tmp->lock);
730 v->___objlocation___=v;
735 /* Array allocation function */
737 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
739 int basesize=length*classsize[type];
740 //round the base size up
741 basesize=(basesize+LOWMASK)&HIGHMASK;
742 int numlocks=basesize>>INDEXSHIFT;
743 int bookkeepsize=(numlocks)*2*sizeof(int);
744 int *tmpint=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+basesize+sizeof(objheader_t)+bookkeepsize);
745 for(;numlocks>0;numlocks--) {
749 objheader_t *tmp=(objheader_t *)tmpint;
750 struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
752 v->lowindex=MAXARRAYSIZE;
754 objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t));
755 struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
758 tmp->lock=RW_LOCK_BIAS;
760 initdsmlocks(&tmp->lock);
766 printf("ERROR: negative array %d\n", length);
769 v->___objlocation___=(struct ___Object___ *)v;
770 v->___length___=length;
776 #if defined(PRECISE_GC)
778 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
779 return allocate_new_mlp(ptr, type, 0, 0);
781 __attribute__((malloc)) void * allocate_new_mlp(void * ptr, int type, int oid, int allocsite) {
783 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
785 struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
797 v->allocsite=allocsite;
802 /* Array allocation function */
804 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
805 return allocate_newarray_mlp(ptr, type, length, 0, 0);
807 __attribute__((malloc)) struct ArrayObject * allocate_newarray_mlp(void * ptr, int type, int length, int oid, int allocsite) {
809 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
811 struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
814 printf("ERROR: negative array\n");
817 v->___length___=length;
828 v->allocsite=allocsite;
834 __attribute__((malloc)) void * allocate_new(int type) {
835 struct ___Object___ * v=FREEMALLOC(classsize[type]);
843 /* Array allocation function */
845 __attribute__((malloc)) struct ArrayObject * allocate_newarray(int type, int length) {
846 __attribute__((malloc)) struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
848 v->___length___=length;
857 /* Converts C character arrays into Java strings */
859 __attribute__((malloc)) struct ___String___ * NewStringShort(void * ptr, const short *str,int length) {
861 __attribute__((malloc)) struct ___String___ * NewStringShort(const short *str,int length) {
865 struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
866 INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
867 struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
868 chararray=(struct ArrayObject *) ptrarray[2];
870 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
871 struct ___String___ * strobj=allocate_new(STRINGTYPE);
873 strobj->___value___=chararray;
874 strobj->___count___=length;
875 strobj->___offset___=0;
877 for(i=0; i<length; i++) {
878 ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=str[i];
883 /* Converts C character arrays into Java strings */
885 __attribute__((malloc)) struct ___String___ * NewString(void * ptr, const char *str,int length) {
887 __attribute__((malloc)) struct ___String___ * NewString(const char *str,int length) {
891 struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
892 INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
893 struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
894 chararray=(struct ArrayObject *) ptrarray[2];
896 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
897 struct ___String___ * strobj=allocate_new(STRINGTYPE);
899 strobj->___value___=chararray;
900 strobj->___count___=length;
901 strobj->___offset___=0;
903 for(i=0; i<length; i++) {
904 ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=(short)str[i];
909 /* Generated code calls this if we fail a bounds check */
911 void failedboundschk(int num) {
913 printf("Array out of bounds\n");
920 longjmp(error_handler,2);
924 /* Abort task call */
927 longjmp(error_handler,4);
929 printf("Aborting\n");
935 #ifdef D___System______Assert____Z
936 void CALL11(___System______Assert____Z, int ___status___, int ___status___) {
938 printf("Assertion violation\n");
939 *((int *)(NULL)); //force stack trace error