BOOL DLLCALL listSemTryWaitBlock(link_list_t* list, unsigned long timeout) { if(list==NULL || !(list->flags&LINK_LIST_SEMAPHORE)) return(FALSE); return(sem_trywait_block(&list->sem,timeout)==0); }
static void sem_test_thread_block(void* arg) { ulong i; thread_data_t* data = (thread_data_t*)arg; printf("sem_test_thread_block entry\n"); sem_post(&data->child_sem); /* signal parent: we've started */ for(i=0;i<10;i++) { if(sem_trywait_block(&data->parent_sem,500)) { printf(" sem_trywait_block() timed out"); sem_wait(&data->parent_sem); } else { printf(" FAILURE: Didn't block"); } printf(" <child>\n"); sem_post(&data->child_sem); } printf("sem_test_thread_block exit\n"); sem_post(&data->child_sem); /* signal parent: we're done */ }
static void output_thread(void* arg) { char stats[128]; BYTE buf[MAX_OUTBUF_SIZE]; int i; ulong avail; ulong total_sent=0; ulong total_pkts=0; ulong short_sends=0; ulong bufbot=0; ulong buftop=0; fd_set socket_set; struct timeval tv; #if 0 /* def _DEBUG */ fprintf(statfp,"output thread started\n"); #endif while(sock!=INVALID_SOCKET && !terminate) { if(bufbot==buftop) avail=RingBufFull(&outbuf); else avail=buftop-bufbot; if(!avail) { #if !defined(RINGBUF_EVENT) SetEvent(outbuf_empty); #endif sem_wait(&outbuf.sem); if(outbuf.highwater_mark) sem_trywait_block(&outbuf.highwater_sem,outbuf_drain_timeout); continue; } /* Check socket for writability (using select) */ tv.tv_sec=0; tv.tv_usec=1000; FD_ZERO(&socket_set); #ifdef __unix__ if(stdio) FD_SET(STDOUT_FILENO,&socket_set); else #endif FD_SET(sock,&socket_set); i=select(sock+1,NULL,&socket_set,NULL,&tv); if(i==SOCKET_ERROR) { lprintf(LOG_ERR,"ERROR %d selecting socket %u for send" ,ERROR_VALUE,sock); break; } if(i<1) { select_errors++; continue; } if(bufbot==buftop) { /* linear buf empty, read from ring buf */ if(avail>sizeof(buf)) { lprintf(LOG_ERR,"Insufficient linear output buffer (%lu > %lu)" ,avail, sizeof(buf)); avail=sizeof(buf); } buftop=RingBufRead(&outbuf, buf, avail); bufbot=0; } #ifdef __unix__ if(stdio) i=write(STDOUT_FILENO, (char*)buf+bufbot, buftop-bufbot); else #endif i=sendsocket(sock, (char*)buf+bufbot, buftop-bufbot); if(i==SOCKET_ERROR) { if(ERROR_VALUE == ENOTSOCK) lprintf(LOG_ERR,"client socket closed on send"); else if(ERROR_VALUE==ECONNRESET) lprintf(LOG_ERR,"connection reset by peer on send"); else if(ERROR_VALUE==ECONNABORTED) lprintf(LOG_ERR,"connection aborted by peer on send"); else lprintf(LOG_ERR,"ERROR %d sending on socket %d" ,ERROR_VALUE, sock); break; } if(debug_tx) dump(buf+bufbot,i); if(i!=(int)(buftop-bufbot)) { lprintf(LOG_ERR,"Short socket send (%u instead of %u)" ,i ,buftop-bufbot); short_sends++; } bufbot+=i; total_sent+=i; total_pkts++; } if(total_sent) sprintf(stats,"(sent %lu bytes in %lu blocks, %lu average, %lu short, %lu errors)" ,total_sent, total_pkts, total_sent/total_pkts, short_sends, select_errors); else stats[0]=0; lprintf(LOG_DEBUG,"output thread terminated\n%s", stats); }
int main() { char str[128]; char compiler[128]; char fpath[MAX_PATH+1]; char* path = "."; char* glob_pattern = "*wrap*"; int i; int ch; uint u; time_t t; glob_t g; DIR* dir; DIRENT* dirent; thread_data_t thread_data; int fd; int fd2; int canrelock=0; clock_t ticks; /* Show platform details */ DESCRIBE_COMPILER(compiler); printf("%-15s: %s\n","Platform",PLATFORM_DESC); printf("%-15s: %s\n","Version",os_version(str)); printf("%-15s: %s\n","Compiler" ,compiler); printf("%-15s: %d\n","Random Number",xp_random(1000)); for(i=0;i<3;i++) { if(_beginthread( sopen_child_thread /* entry point */ ,0 /* stack size (0=auto) */ ,(void*)i /* data */ )==(unsigned long)-1) printf("_beginthread failed\n"); else SLEEP(1); } printf("Waiting for all sopen_child_threads to close...\n"); SLEEP(5000); /* wait for all threads to quit */ /* Exclusive sopen test */ printf("\nsopen() test\n"); if((fd=sopen(LOCK_FNAME,O_RDWR|O_CREAT,SH_DENYRW,S_IREAD|S_IWRITE))==-1) { perror(LOCK_FNAME); return(errno); } printf("%s is opened with an exclusive (read/write) lock\n",LOCK_FNAME); getkey(); if(_beginthread( sopen_test_thread /* entry point */ ,0 /* stack size (0=auto) */ ,NULL /* data */ )==(unsigned long)-1) printf("_beginthread failed\n"); else SLEEP(1000); close(fd); /* sopen()/lock test */ printf("\nlock() test\n"); if((fd=sopen(LOCK_FNAME,O_RDWR|O_CREAT,SH_DENYNO,S_IREAD|S_IWRITE))==-1) { perror(LOCK_FNAME); return(errno); } write(fd,"lock testing\n",LOCK_LEN); if(lock(fd,LOCK_OFFSET,LOCK_LEN)==0) printf("lock() succeeds\n"); else printf("!FAILURE: lock() non-functional (or file already locked)\n"); if(lock(fd,LOCK_OFFSET,LOCK_LEN)==0) { printf("!FAILURE: Subsequent lock of region was allowed (will skip some tests)\n"); canrelock=1; } if(_beginthread( lock_test_thread /* entry point */ ,0 /* stack size (0=auto) */ ,NULL /* data */ )==(unsigned long)-1) printf("_beginthread failed\n"); else SLEEP(1000); if(canrelock) printf("?? Skipping some tests due to inability to detect own locks\n"); else { if(lock(fd,LOCK_OFFSET,LOCK_LEN)) printf("Locks in first thread survive open()/close() in other thread\n"); else printf("!FAILURE: lock() in first thread lost by open()/close() in other thread\n"); if(lock(fd,LOCK_OFFSET+LOCK_LEN+1,LOCK_LEN)) printf("!FAILURE: file locking\n"); else printf("Record locking\n"); } if((fd2=sopen(LOCK_FNAME,O_RDWR,SH_DENYRW))==-1) { printf("Cannot reopen SH_DENYRW while lock is held\n"); close(fd2); } else { printf("!FAILURE: can reopen SH_DENYRW while lock is held\n"); } if(unlock(fd,LOCK_OFFSET,LOCK_LEN)) printf("!FAILURE: unlock() non-functional\n"); if(lock(fd,LOCK_OFFSET+LOCK_LEN+1,LOCK_LEN)) printf("Cannot re-lock after non-overlapping unlock()\n"); else printf("!FAILURE: can re-lock after non-overlappping unlock()\n"); if(lock(fd,LOCK_OFFSET,LOCK_LEN)) printf("!FAILURE: cannot re-lock unlocked area\n"); close(fd); /* getch test */ printf("\ngetch() test (ESC to continue)\n"); do { ch=getch(); printf("getch() returned %d\n",ch); } while(ch!=ESC); /* kbhit test */ printf("\nkbhit() test (any key to continue)\n"); while(!kbhit()) { printf("."); fflush(stdout); SLEEP(500); } getch(); /* remove character from keyboard buffer */ /* BEEP test */ printf("\nBEEP() test\n"); getkey(); for(i=750;i>250;i-=5) BEEP(i,15); for(;i<1000;i+=5) BEEP(i,15); /* SLEEP test */ printf("\nSLEEP(5 second) test\n"); getkey(); t=time(NULL); printf("sleeping... "); fflush(stdout); ticks=msclock(); SLEEP(5000); printf("slept %ld seconds (%ld according to msclock)\n",time(NULL)-t,(msclock()-ticks)/MSCLOCKS_PER_SEC); /* Thread SLEEP test */ printf("\nThread SLEEP(5 second) test\n"); getkey(); i=0; if(_beginthread( sleep_test_thread /* entry point */ ,0 /* stack size (0=auto) */ ,&i /* data */ )==(unsigned long)-1) printf("_beginthread failed\n"); else { SLEEP(1); /* yield to child thread */ while(i==0) { printf("."); fflush(stdout); SLEEP(1000); } } /* glob test */ printf("\nglob(%s) test\n",glob_pattern); getkey(); i=glob(glob_pattern,GLOB_MARK,NULL,&g); if(i==0) { for(u=0;u<g.gl_pathc;u++) printf("%s\n",g.gl_pathv[u]); globfree(&g); } else printf("glob(%s) returned %d\n",glob_pattern,i); /* opendir (and other directory functions) test */ printf("\nopendir(%s) test\n",path); getkey(); printf("\nDirectory of %s\n\n",FULLPATH(fpath,path,sizeof(fpath))); dir=opendir(path); while(dir!=NULL && (dirent=readdir(dir))!=NULL) { t=fdate(dirent->d_name); printf("%.24s %10lu %06o %s%c\n" ,ctime(&t) ,flength(dirent->d_name) ,getfattr(dirent->d_name) ,dirent->d_name ,isdir(dirent->d_name) ? '/':0 ); } if(dir!=NULL) closedir(dir); printf("\nFree disk space: %lu kbytes\n",getfreediskspace(path,1024)); /* Thread (and inter-process communication) test */ printf("\nSemaphore test\n"); getkey(); if(sem_init(&thread_data.parent_sem ,0 /* shared between processes */ ,0 /* initial count */ )) { printf("sem_init failed\n"); } if(sem_init(&thread_data.child_sem ,0 /* shared between processes */ ,0 /* initial count */ )) { printf("sem_init failed\n"); } if(_beginthread( sem_test_thread /* entry point */ ,0 /* stack size (0=auto) */ ,&thread_data /* data */ )==(unsigned long)-1) printf("_beginthread failed\n"); else { sem_wait(&thread_data.child_sem); /* wait for thread to begin */ for(i=0;i<10;i++) { printf("<parent>"); sem_post(&thread_data.parent_sem); sem_wait(&thread_data.child_sem); } sem_wait(&thread_data.child_sem); /* wait for thread to end */ } sem_destroy(&thread_data.parent_sem); sem_destroy(&thread_data.child_sem); printf("\nSemaphore blocking test\n"); getkey(); sem_init(&thread_data.parent_sem ,0 /* shared between processes */ ,0 /* initial count */ ); sem_init(&thread_data.child_sem ,0 /* shared between processes */ ,0 /* initial count */ ); if(_beginthread( sem_test_thread_block /* entry point */ ,0 /* stack size (0=auto) */ ,&thread_data /* data */ )==(unsigned long)-1) printf("_beginthread failed\n"); else { sem_wait(&thread_data.child_sem); /* wait for thread to begin */ for(i=0;i<10;i++) { printf("<parent>"); SLEEP(5000); sem_post(&thread_data.parent_sem); sem_wait(&thread_data.child_sem); } sem_wait(&thread_data.child_sem); /* wait for thread to end */ } printf("\nsem_trywait_block test..."); t=time(NULL); sem_trywait_block(&thread_data.parent_sem,5000); printf("\ntimed-out after %ld seconds (should be 5 seconds)\n",time(NULL)-t); sem_destroy(&thread_data.parent_sem); sem_destroy(&thread_data.child_sem); printf("\nendian check..."); memcpy(&i,"\x01\x02\x03\x04",4); if(LE_LONG(i)==67305985) { printf("OK!\n"); } else { printf("FAILED!\n"); } return 0; }