comparison gtk/dw.c @ 557:1a210e2f214b

Added a bunch of support routines I now own due to the settlement agreement with F/X. Shared memory and named event semaphores in particular.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sat, 17 Apr 2004 05:38:09 +0000
parents f4093dce8155
children 05060ce4d6ae
comparison
equal deleted inserted replaced
556:f4093dce8155 557:1a210e2f214b
7366 *eve = NULL; 7366 *eve = NULL;
7367 7367
7368 return TRUE; 7368 return TRUE;
7369 } 7369 }
7370 7370
7371 struct _seminfo {
7372 int fd;
7373 int waiting;
7374 };
7375
7376 static void _handle_sem(int *tmpsock)
7377 {
7378 fd_set rd;
7379 struct _seminfo *array = (struct _seminfo *)malloc(sizeof(struct _seminfo));
7380 int listenfd = tmpsock[0];
7381 int bytesread, connectcount = 1, maxfd, z, posted = 0;
7382 char command;
7383 sigset_t mask;
7384
7385 sigfillset(&mask); /* Mask all allowed signals */
7386 pthread_sigmask(SIG_BLOCK, &mask, NULL);
7387
7388 /* problems */
7389 if(tmpsock[1] == -1)
7390 {
7391 free(array);
7392 return;
7393 }
7394
7395 array[0].fd = tmpsock[1];
7396 array[0].waiting = 0;
7397
7398 /* Free the memory allocated in dw_named_event_new. */
7399 free(tmpsock);
7400
7401 while(1)
7402 {
7403 FD_ZERO(&rd);
7404 FD_SET(listenfd, &rd);
7405
7406 maxfd = listenfd;
7407
7408 /* Added any connections to the named event semaphore */
7409 for(z=0;z<connectcount;z++)
7410 {
7411 if(array[z].fd > maxfd)
7412 maxfd = array[z].fd;
7413
7414 FD_SET(array[z].fd, &rd);
7415 }
7416
7417 if(select(maxfd+1, &rd, NULL, NULL, NULL) == -1)
7418 return;
7419
7420 if(FD_ISSET(listenfd, &rd))
7421 {
7422 struct _seminfo *newarray;
7423 int newfd = accept(listenfd, 0, 0);
7424
7425 if(newfd > -1)
7426 {
7427 /* Add new connections to the set */
7428 newarray = (struct _seminfo *)malloc(sizeof(struct _seminfo)*(connectcount+1));
7429 memcpy(newarray, array, sizeof(struct _seminfo)*(connectcount));
7430
7431 newarray[connectcount].fd = newfd;
7432 newarray[connectcount].waiting = 0;
7433
7434 connectcount++;
7435
7436 /* Replace old array with new one */
7437 free(array);
7438 array = newarray;
7439 }
7440 }
7441
7442 /* Handle any events posted to the semaphore */
7443 for(z=0;z<connectcount;z++)
7444 {
7445 if(FD_ISSET(array[z].fd, &rd))
7446 {
7447 if((bytesread = read(array[z].fd, &command, 1)) < 1)
7448 {
7449 struct _seminfo *newarray;
7450
7451 /* Remove this connection from the set */
7452 newarray = (struct _seminfo *)malloc(sizeof(struct _seminfo)*(connectcount-1));
7453 if(!z)
7454 memcpy(newarray, &array[1], sizeof(struct _seminfo)*(connectcount-1));
7455 else
7456 {
7457 memcpy(newarray, array, sizeof(struct _seminfo)*z);
7458 if(z!=(connectcount-1))
7459 memcpy(&newarray[z], &array[z+1], sizeof(struct _seminfo)*(z-connectcount-1));
7460 }
7461 connectcount--;
7462
7463 /* Replace old array with new one */
7464 free(array);
7465 array = newarray;
7466 }
7467 else if(bytesread == 1)
7468 {
7469 switch(command)
7470 {
7471 case 0:
7472 {
7473 /* Reset */
7474 posted = 0;
7475 }
7476 break;
7477 case 1:
7478 /* Post */
7479 {
7480 int s;
7481 char tmp = (char)0;
7482
7483 posted = 1;
7484
7485 for(s=0;s<connectcount;s++)
7486 {
7487 /* The semaphore has been posted so
7488 * we tell all the waiting threads to
7489 * continue.
7490 */
7491 if(array[s].waiting)
7492 write(array[s].fd, &tmp, 1);
7493 }
7494 }
7495 break;
7496 case 2:
7497 /* Wait */
7498 {
7499 char tmp = (char)0;
7500
7501 array[z].waiting = 1;
7502
7503 /* If we are posted exit immeditately */
7504 if(posted)
7505 write(array[z].fd, &tmp, 1);
7506 }
7507 break;
7508 case 3:
7509 {
7510 /* Done Waiting */
7511 array[z].waiting = 0;
7512 }
7513 break;
7514 }
7515 }
7516 }
7517 }
7518
7519 }
7520
7521 }
7522
7523 /* Using domain sockets on unix for IPC */
7524 /* Create a named event semaphore which can be
7525 * opened from other processes.
7526 * Parameters:
7527 * eve: Pointer to an event handle to receive handle.
7528 * name: Name given to semaphore which can be opened
7529 * by other processes.
7530 */
7531 HEV dw_named_event_new(char *name)
7532 {
7533 struct sockaddr_un un;
7534 int ev, *tmpsock = (int *)malloc(sizeof(int)*2);
7535 DWTID dwthread;
7536
7537 if(!tmpsock)
7538 return DB_EVENT_NO_MEM;
7539
7540 tmpsock[0] = socket(AF_UNIX, SOCK_STREAM, 0);
7541 ev = socket(AF_UNIX, SOCK_STREAM, 0);
7542 memset(&un, 0, sizeof(un));
7543 un.sun_family=AF_UNIX;
7544 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
7545 strcpy(un.sun_path, "/tmp/.dw/");
7546 strcat(un.sun_path, name);
7547
7548 /* just to be safe, this should be changed
7549 * to support multiple instances.
7550 */
7551 remove(un.sun_path);
7552
7553 bind(tmpsock[0], (struct sockaddr *)&un, sizeof(un));
7554 listen(tmpsock[0], 0);
7555 connect(ev, (struct sockaddr *)&un, sizeof(un));
7556 tmpsock[1] = accept(tmpsock[0], 0, 0);
7557
7558 if(tmpsock[0] < 0 || tmpsock[1] < 0 || ev < 0)
7559 {
7560 if(tmpsock[0] > -1)
7561 close(tmpsock[0]);
7562 if(tmpsock[1] > -1)
7563 close(tmpsock[1]);
7564 if(ev > -1)
7565 close(ev);
7566 free(tmpsock);
7567 return 0;
7568 }
7569
7570 /* Create a thread to handle this event semaphore */
7571 pthread_create(&dwthread, NULL, (void *)_handle_sem, (void *)tmpsock);
7572 return ev;
7573 }
7574
7575 /* Open an already existing named event semaphore.
7576 * Parameters:
7577 * eve: Pointer to an event handle to receive handle.
7578 * name: Name given to semaphore which can be opened
7579 * by other processes.
7580 */
7581 HEV dw_named_event_get(char *name)
7582 {
7583 struct sockaddr_un un;
7584 int ev = socket(AF_UNIX, SOCK_STREAM, 0);
7585 if(ev < 0)
7586 return 0;
7587
7588 un.sun_family=AF_UNIX;
7589 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
7590 strcpy(un.sun_path, "/tmp/.dw/");
7591 strcat(un.sun_path, name);
7592 connect(ev, (struct sockaddr *)&un, sizeof(un));
7593 return ev;
7594 }
7595
7596 /* Resets the event semaphore so threads who call wait
7597 * on this semaphore will block.
7598 * Parameters:
7599 * eve: Handle to the semaphore obtained by
7600 * an open or create call.
7601 */
7602 int dw_named_event_reset(HEV eve)
7603 {
7604 /* signal reset */
7605 char tmp = (char)0;
7606
7607 if(eve < 0)
7608 return 0;
7609
7610 if(write(eve, &tmp, 1) == 1)
7611 return 0;
7612 return 1;
7613 }
7614
7615 /* Sets the posted state of an event semaphore, any threads
7616 * waiting on the semaphore will no longer block.
7617 * Parameters:
7618 * eve: Handle to the semaphore obtained by
7619 * an open or create call.
7620 */
7621 int dw_named_event_post(HEV eve)
7622 {
7623
7624 /* signal post */
7625 char tmp = (char)1;
7626
7627 if(eve < 0)
7628 return 0;
7629
7630 if(write(eve, &tmp, 1) == 1)
7631 return 0;
7632 return 1;
7633 }
7634
7635 /* Waits on the specified semaphore until it becomes
7636 * posted, or returns immediately if it already is posted.
7637 * Parameters:
7638 * eve: Handle to the semaphore obtained by
7639 * an open or create call.
7640 * timeout: Number of milliseconds before timing out
7641 * or -1 if indefinite.
7642 */
7643 int dw_named_event_wait(HEV eve, unsigned long timeout)
7644 {
7645 fd_set rd;
7646 struct timeval tv, *useme;
7647 int retval = 0;
7648 char tmp;
7649
7650 if(eve < 0)
7651 return DB_EVENT_NON_INIT;
7652
7653 /* Set the timout or infinite */
7654 if(timeout == -1)
7655 useme = NULL;
7656 else
7657 {
7658 tv.tv_sec = timeout / 1000;
7659 tv.tv_usec = timeout % 1000;
7660
7661 useme = &tv;
7662 }
7663
7664 FD_ZERO(&rd);
7665 FD_SET(eve, &rd);
7666
7667 /* Signal wait */
7668 tmp = (char)2;
7669 write(eve, &tmp, 1);
7670
7671 retval = select(eve+1, &rd, NULL, NULL, useme);
7672
7673 /* Signal done waiting. */
7674 tmp = (char)3;
7675 write(eve, &tmp, 1);
7676
7677 if(retval == 0)
7678 return DW_EVENT_TIMEOUT;
7679 else if(retval == -1)
7680 return DW_EVENT_INTERRUPT;
7681
7682 /* Clear the entry from the pipe so
7683 * we don't loop endlessly. :)
7684 */
7685 read(eve, &tmp, 1);
7686 return 0;
7687 }
7688
7689 /* Release this semaphore, if there are no more open
7690 * handles on this semaphore the semaphore will be destroyed.
7691 * Parameters:
7692 * eve: Handle to the semaphore obtained by
7693 * an open or create call.
7694 */
7695 int dw_named_event_close(HEV eve)
7696 {
7697 /* Finally close the domain socket,
7698 * cleanup will continue in _handle_sem.
7699 */
7700 close(eve);
7701 return 0;
7702 }
7703
7371 /* 7704 /*
7372 * Setup thread independent color sets. 7705 * Setup thread independent color sets.
7373 */ 7706 */
7374 void _dwthreadstart(void *data) 7707 void _dwthreadstart(void *data)
7375 { 7708 {
7380 7713
7381 _dw_thread_add(dw_thread_id()); 7714 _dw_thread_add(dw_thread_id());
7382 threadfunc(tmp[1]); 7715 threadfunc(tmp[1]);
7383 _dw_thread_remove(dw_thread_id()); 7716 _dw_thread_remove(dw_thread_id());
7384 free(tmp); 7717 free(tmp);
7718 }
7719
7720 /*
7721 * Allocates a shared memory region with a name.
7722 * Parameters:
7723 * handle: A pointer to receive a SHM identifier.
7724 * dest: A pointer to a pointer to receive the memory address.
7725 * size: Size in bytes of the shared memory region to allocate.
7726 * name: A string pointer to a unique memory name.
7727 */
7728 HSHM dw_named_memory_new(void **dest, int size, char *name)
7729 {
7730 char namebuf[1024];
7731 HSHM handle;
7732
7733 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
7734 sprintf(namebuf, "/tmp/.dw/%s", name);
7735
7736 if((handle->fd = open(namebuf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0)
7737 return 0;
7738
7739 ftruncate(handle->fd, size);
7740
7741 /* attach the shared memory segment to our process's address space. */
7742 *dest = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
7743
7744 if(*dest == MAP_FAILED)
7745 {
7746 close(handle->fd);
7747 *dest = NULL;
7748 return 0;
7749 }
7750
7751 handle->size = size;
7752 handle->sid = getsid(0);
7753 handle->path = strdup(namebuf);
7754
7755 return handle;
7756 }
7757
7758 /*
7759 * Aquires shared memory region with a name.
7760 * Parameters:
7761 * dest: A pointer to a pointer to receive the memory address.
7762 * size: Size in bytes of the shared memory region to requested.
7763 * name: A string pointer to a unique memory name.
7764 */
7765 HSHM dw_named_memory_get(void **dest, int size, char *name)
7766 {
7767 char namebuf[1024];
7768 HSHM handle;
7769
7770 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
7771 sprintf(namebuf, "/tmp/.dw/%s", name);
7772
7773 if((handle->fd = open(namebuf, O_RDWR)) < 0)
7774 return -1;
7775
7776 /* attach the shared memory segment to our process's address space. */
7777 *dest = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
7778
7779 if(*dest == MAP_FAILED)
7780 {
7781 close(handle->fd);
7782 *dest = NULL;
7783 return 0;
7784 }
7785
7786 handle->size = size;
7787 handle->sid = -1;
7788 handle->path = NULL;
7789
7790 return handle;
7791 }
7792
7793 /*
7794 * Frees a shared memory region previously allocated.
7795 * Parameters:
7796 * handle: Handle obtained from DB_named_memory_allocate.
7797 * ptr: The memory address aquired with DB_named_memory_allocate.
7798 */
7799 int dw_named_memory_free(HSHM handle, void *ptr)
7800 {
7801 int rc = munmap(ptr, handle.size);
7802
7803 close(handle.fd);
7804 if(handle.path)
7805 {
7806 /* Only remove the actual file if we are the
7807 * creator of the file.
7808 */
7809 if(handle.sid != -1 && handle.sid == getsid(0))
7810 remove(handle.path);
7811 free(handle.path);
7812 }
7813 return rc;
7385 } 7814 }
7386 /* 7815 /*
7387 * Creates a new thread with a starting point of func. 7816 * Creates a new thread with a starting point of func.
7388 * Parameters: 7817 * Parameters:
7389 * func: Function which will be run in the new thread. 7818 * func: Function which will be run in the new thread.