Dear ROOTers, we continued our investigations on the usage of threads within ROOT (see http://www-wnt.gsi.de/go4/Threads/tthread.htm) and found some interesting behaviour. Using the TThread classes provided in the framework of ROOT (e.g. 2.22), we found, that on our working environment here at GSI (Linux Debian 2.1, kernel 2.0.36, glibc 2.0, XFree 3.3.2 on SMP machines with two CPUs) all actions on the TCanvas from within threads causes nearly instantaniously a segmentation violation. Having also access to single CPU machines we found, that the identical program (which starts several threads and each accesses the canvas) works! Thus the mechanism provided by ROOT to protect the canvas from accesses by different threads at the same time works in principle, but there seems to be a problem in the interplay between ROOT and the Xlib. Since the X11R6 is stated to be thread-safe, we wanted now to check on the experimental SMP-support in the kernel in use. So I created a simple C-program, based only on calls to the Xlib and to the pthreads, which reproduces the error on SMP-machines but runs on single-CPU machines. We would greatly appreciate any help from anybody outside, who has access to an SMP-machine with a newer kernel (like 2.2.x). Just compile the attached program on your machine and try wether it runs stable, also introducing different timing values (by the sleep/usleep). Any response to that problem is greatly appreciated. We try currently to draw our conclusions from the findings we have here about the use of threads within our GO4 project. Greetings, Marc ---------------------------------------- Dr. Marc Hemberger GSI, Abteilung DV&EE Planckstr. 1 64291 Darmstadt M.Hemberger@gsi.de /* X lib program with multithreading, the timing introduced by the sleep/usleep commands is essential for the program */ #include <stdio.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xresource.h> #include <X11/keysym.h> #include <math.h> #include <pthread.h> #define EXIT_FAILURE 1 pthread_t tid1, tid2, tid3; pthread_attr_t t_attr; pthread_mutex_t mut1; pthread_mutexattr_t attr; int counter=0; Bool propagate = False; Display *display; /* Server or display to which a connection will be made */ int screen; /* Screen number to use on that display */ Window win; /* The applications one and only window */ XEvent event; /* The event data structure */ GC gc1, gc2; /* Graphics context data structures */ XGCValues gs1,gs2; /* Graphics context settings */ char *message; /* Message printed in window */ char mess[] = { "000000000" }; static char progDefaultMessage[] = {"A Simple Xlib Program"}; extern int counter; void setUpGCs(); void drawInToWindow(); void drawCountWindow(); void thread1(); void thread2(); void thread3(); void threadex(); int main(argc, argv) int argc; char **argv; { int count, *rc; /* Attempt to connect to the server and use the default screen */ if ((display = XOpenDisplay(NULL)) == NULL) { perror("Can't connect to server"); exit(1); } screen = DefaultScreen(display); /* Create a window */ win = XCreateSimpleWindow(display, RootWindow(display, screen), 100, 200, 400, 300, 1, BlackPixel(display, screen), WhitePixel(display, screen)); /* Set up which event types the window will handle */ XSelectInput(display, win, ExposureMask | ButtonPressMask); /* Graphics contexts */ setUpGCs(); /* Attempt to get message from user-defined resource setting */ if ((message = XGetDefault(display, "win", "message")) == NULL) message = progDefaultMessage; /* Map the window in order for it to be displayed */ XMapWindow(display, win); threadex(); /* Enter an infinite loop, awaiting and responding to the chosen events */ count = 0; while (1) { XNextEvent(display, &event); switch (event.type) { case Expose: drawInToWindow(); break; /* Draw/re-draw everything */ case ButtonPress: exit(0); break; /* Quit on mouse button press */ default: break; } if(counter > 99999) { if(pthread_mutex_lock(&mut1) == -1) { perror("pthread_mutex_lock"); exit(EXIT_FAILURE); } counter = 0; count ++; if(pthread_mutex_unlock(&mut1) == -1) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } fprintf(stderr, "counter reset %d\n", count); } } } void setUpGCs() /* Set up 2 graphics context resources in the display server */ /* gc1 for message and rectangle; gc2 for ellipse */ { /* Define a bitmap for the stipple pattern used to fill the ellipse */ #define stipple_width 3 #define stipple_height 3 static char stipple_bits[] = {0x02, 0x05, 0x02}; Pixmap stipple; /* Create the stipple for ellipse fill pattern of gc2 */ if ((stipple = XCreateBitmapFromData(display, RootWindow(display, screen), stipple_bits, stipple_width, stipple_height)) == 0) { perror("Can't create bitmap"); exit(1); } gc1 = XCreateGC(display, win, 0, &gs1); /* 0 -> use defaults */ gc2 = XCreateGC(display, win, 0, &gs2); /* 0 -> use defaults */ /* Now override some of the defaults */ XSetForeground(display, gc1, BlackPixel(display, screen)); XSetBackground(display, gc1, WhitePixel(display, screen)); XSetLineAttributes(display, gc1, 2, LineSolid, CapRound, JoinRound); XSetStipple(display, gc2, stipple); XSetFillStyle(display, gc2, FillOpaqueStippled); } void drawInToWindow() { /* Print message, draw restangle and filled ellipse as defined */ /* by the GC */ XDrawString(display, win, gc1, 130, 20, message, strlen(message)); XDrawRectangle(display, win, gc1, 40, 40, 320, 220); XFillArc(display, win, gc2, 50, 50, 300, 200, 0, 360*64); } void drawCountWindow() { XSendEvent(display, win, propagate, ExposureMask, &event); } void thread1() { static int count = 0; while(1) { if(pthread_mutex_lock(&mut1) == -1) { perror("pthread_mutex_lock"); exit(EXIT_FAILURE); } count++; counter = counter + 1; /* fprintf(stderr, "T1=%02d %02d ", counter, count); */ if(pthread_mutex_unlock(&mut1) == -1) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } XFillRectangle(display, win, gc1, 308, 8, 50, 15); sprintf(mess, "%s %05d", "T1", counter); XSetForeground(display, gc1, WhitePixel(display, screen)); XDrawString(display, win, gc1, 310, 20, mess, strlen(mess)); XSetForeground(display, gc1, BlackPixel(display, screen)); XSendEvent(display, win, propagate, ExposureMask, &event); sleep(1); /* <======= introduce tming here! */ /* usleep(100000); *//* <== this does not work !! */ } } void thread2() { static int count = 0; while(1) { if(pthread_mutex_lock(&mut1) == -1) { perror("pthread_mutex_lock"); exit(EXIT_FAILURE); } count++; counter = counter + 1; /* fprintf(stderr, "\tT2=%02d %02d ", counter, count); */ if(pthread_mutex_unlock(&mut1) == -1) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } XFillRectangle(display, win, gc1, 48, 8, 50, 15); sprintf(mess, "%s %05d", "T2", counter); XSetForeground(display, gc1, WhitePixel(display, screen)); XDrawString(display, win, gc1, 50, 20, mess, strlen(mess)); XSetForeground(display, gc1, BlackPixel(display, screen)); XSendEvent(display, win, propagate, ExposureMask, &event); usleep(378000); /* <======= introduce tming here! */ /* usleep(200000); *//* <== this does not work !! */ } } void thread3() { static int count = 0; while(1) { if(pthread_mutex_lock(&mut1) == -1) { perror("pthread_mutex_lock"); exit(EXIT_FAILURE); } count++; counter = counter + 1; /* fprintf(stderr, "\tT3=%02d %02d ", counter, count); */ if(pthread_mutex_unlock(&mut1) == -1) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } XSendEvent(display, win, propagate, ExposureMask, &event); usleep(734000); /* <======= introduce tming here! */ /* usleep(150000); */ /* <== this does not work !! */ } } void threadex() { if(pthread_mutexattr_init(&attr) == -1) { perror("pthread_mutexattr_create"); exit(EXIT_FAILURE); } if(pthread_mutex_init(&mut1, &attr) == -1) { perror("pthread_mutex_init"); exit(EXIT_FAILURE); } if(pthread_attr_init(&t_attr) == -1) { perror("pthread_attr_create"); exit(EXIT_FAILURE); } if(pthread_create(&tid1, &t_attr, thread1, 0) == -1) { perror("pthread_create(1)"); exit(EXIT_FAILURE); } if(pthread_create(&tid2, &t_attr, thread2, 0) == -1) { perror("pthread_create(2)"); exit(EXIT_FAILURE); } if(pthread_create(&tid3, &t_attr, thread3, 0) == -1) { perror("pthread_create(3)"); exit(EXIT_FAILURE); } /* for(;;) pause(); */ } # ========================= Ultrix: =========================== # CC = egcc O = o # To enable debugging use '-g' option for compile step: # CFLAGS = -g -D_CFORTRAN2_VERSION_ -gen_feedback # CFLAGS = -g -D__STDC__ -Dconst=" " -D__LANGUAGE_C -D__mips -DDEBUG CFLAGS = -Wall -O3 # cc CFLAGS = -w0 -O3 or -g0 -g1 -g2 -g3 on levi # To enable profiling use '-p' option for link step: # LFLAGS = -p1 -pg # LFLAGS = -Wl,-yprob_ LFLAGS = LINK = egcc OUTPUT = -o ### The blank before the '#' is required! MATHLIB = -lm EXE = LIB = a F77COMP = g77 -c F77 = g77 FFLAGS = -static -g -warn unused -O3 # for profiling enable -g3 # FFLAGS = -static -g -g3 # Symbols for linking with libraries: # FPLIB = -L/us0/vlk/hemberg/fpack -lfpack08604 # CERNLIB = -L/cern/pro/lib -lkernlib -lpacklib \ # -lUfor -lfor -lFutil -lm -lots -lc XLIB = -L/usr/X11/lib -lX11 -lXm -lXaw -lXp -lXpm VOGLLIB= -L/u/hemberg/ftp/vogle-3.0/src -lvogle # MIZZILIB= -L/us0/vlk/hemberg/ccl -lccl DIVLIB= -lpthread GRAFLIB= -L/cern/pro/lib -lgraflib -lgrafX11 # PGPLOT= -lcpgplot -lpgplot MATHLIB = -lm CPPLIB = -lstdc++ winthread2$(EXE): winthread2.$(O) $(LINK) $(LFLAGS) winthread2.$(O) $(DIVLIB) $(XLIB) $(OUTPUT) winthread2 winthread2.$(O): winthread2.c
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:38 MET