Mercurial > dwindows
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. |