static void thread_getkey () { KBDKEYINFO keyInfo; int n; while (!atEnd) { /* at end is a flag */ set_kbd(); KbdCharIn(&keyInfo, IO_NOWAIT, 0); /* get a character */ if (keyInfo.fbStatus & 0x040) { /* found a char process it */ if (keyInfo.chChar == SLang_Abort_Char) { if (SLang_Ignore_User_Abort == 0) SLang_set_error (SL_USER_BREAK); SLKeyBoard_Quit = 1; } n = (endBuf + 1) % BUFFER_LEN; if (n == startBuf) { DosBeep (500, 20); KbdFlushBuffer(0); continue; } RequestSem(); threadKeys [n].ascii = keyInfo.chChar; threadKeys [n].scan = keyInfo.chScan; /* threadKeys [n].shift = keyInfo.fsState; */ endBuf = n; ReleaseSem(); } else /* no char available*/ DosSleep (20); } }
int DzReleaseSem( DzHandle sem, int count ) { DzHost* host = GetHost(); assert( host ); assert( sem->type == TYPE_SEM ); assert( count > 0 ); assert( sem->notifyCount + count > sem->notifyCount ); return ReleaseSem( host, sem, count ); }
static void *thread_start(void *arg) { void (*F) (void*); void *args; F = ((thread_args_t *)arg)->F; args = ((thread_args_t *)arg)->args; #ifdef HAVE_GETTID ((thread_args_t *)arg)->tid = PID(); #endif ReleaseSem(&((thread_args_t *)arg)->mutex); pthread_detach(pthread_self()); F(args); return NULL; }
/* Release memory from errlist, release semaphore */ void ReleaseErrorList(void){ pStrErrList el; if( err_sem_init ){ if( errlist && !LockSem(&err_sem) ){ while(errlist){ if(errlist->text) free(errlist->text); el = errlist; errlist=errlist->next; free(el); } ReleaseSem(&err_sem); } err_sem_init=0; CleanSem(&err_sem); } }
void rel_grow_handles(int nh) { LONG addfh=0; static ULONG curmaxfh=0; LockSem(&fhsem); if (curmaxfh == 0) { if (DosSetRelMaxFH(&addfh, &curmaxfh)) { Log(1, "Cannot DosSetRelMaxFH"); return; } } #ifdef __WATCOMC__ if ((addfh=_grow_handles((int)(curmaxfh += nh))) < curmaxfh) #else addfh=nh; if (DosSetRelMaxFH(&addfh, &curmaxfh)) #endif Log(1, "Cannot grow handles to %ld (now %ld): %s", curmaxfh, addfh, strerror(errno)); else Log(6, "Set MaxFH to %ld (res %ld)", curmaxfh, addfh); ReleaseSem(&fhsem); }
/* Return error message from errlist */ const char *errorfromlist(int err){ pStrErrList el, sel; const char *errmess=""; for( sel=el=errlist; el; el=el->next ) if( el->code==err ) return el->text; if(!err_sem_init){ err_sem_init=1; InitSem(&err_sem); } if( !LockSem(&err_sem) ){ if(sel!=errlist) /* List changed, check again */ for( el=errlist; el && (el!=sel); el=el->next ) if( el->code==err ){ errmess = el->text; goto skip_newerrortolist; } errmess = newerrortolist(err); skip_newerrortolist: ReleaseSem(&err_sem); } return errmess; }
unsigned int _pSLsys_getkey () { unsigned int c; unsigned char scan; if (!keyWaiting()) { int tsecs = 300; while (!_pSLsys_input_pending(tsecs)) ; } /* read codes from buffer */ RequestSem(); startBuf = (startBuf + 1) % BUFFER_LEN; c = threadKeys [startBuf].ascii; scan = threadKeys [startBuf].scan; ReleaseSem(); switch (c) { case 8: if (scan == 0x0E) c = 127; break; case 0xE0: case 0: c = _pSLpc_convert_scancode (scan, 0, 1); break; default: break; } return (c); }
int branch (register void (*F) (void *), register void *arg, register size_t size) { register int rc; char *tmp; /* We make our own copy of arg for the child as the parent may destroy it * before the child finish to use it. It's not really needed with fork() * but we do not want extra checks for HAVE_FORK before free(arg) in the * child. */ if (size > 0) { if ((tmp = malloc (size)) == NULL) { Log (1, "malloc failed"); return -1; } else { memcpy (tmp, arg, size); arg = tmp; } } else arg = 0; #if defined(HAVE_FORK) && !defined(HAVE_THREADS) && !defined(AMIGA) && !defined(DEBUGCHILD) again: if (!(rc = fork ())) { /* new process */ mypid = getpid(); F (arg); exit (0); } else if (rc < 0) { if (errno == EINTR) goto again; /* parent, error */ Log (1, "fork: %s", strerror (errno)); } else { /* parent, free our copy of args */ xfree (arg); } #endif #if defined(HAVE_THREADS) && !defined(DEBUGCHILD) #ifdef WITH_PTHREADS { thread_args_t args; pthread_t tid; args.F = F; args.args = arg; InitSem(&args.mutex); LockSem(&args.mutex); if ((rc = pthread_create (&tid, NULL, thread_start, &args)) != 0) { Log (1, "pthread_create: %s", strerror (rc)); rc = -1; } else { LockSem(&args.mutex); /* wait until thread releases this mutex */ #ifdef HAVE_GETTID rc = args.tid; #else rc = (int)(0xffff & (long int)tid); #endif } ReleaseSem(&args.mutex); CleanSem(&args.mutex); } #else if ((rc = BEGINTHREAD (F, STACKSIZE, arg)) < 0) Log (1, "_beginthread: %s", strerror (errno)); #endif #endif #ifdef AMIGA /* this is rather bizzare. this function pretends to be a fork and behaves * like one, but actually it's a kind of a thread. so we'll need semaphores */ if (!(rc = ix_vfork ())) { vfork_setup_child (); ix_vfork_resume (); F (arg); exit (0); } else if (rc < 0) { Log (1, "ix_vfork: %s", strerror (errno)); } #endif #if defined(DOS) || defined(DEBUGCHILD) rc = 0; F (arg); #endif return rc; }
/* * Run one client loop. Return -1 to exit */ static int do_client(BINKD_CONFIG *config) { FTN_NODE *r; int pid; if (!config->q_present) { q_free (SCAN_LISTED, config); if (config->printq) Log (-1, "scan\r"); q_scan (SCAN_LISTED, config); config->q_present = 1; if (config->printq) { LockSem (&lsem); q_list (stderr, SCAN_LISTED, config); ReleaseSem (&lsem); Log (-1, "idle\r"); } } if (n_clients < config->max_clients) { if ((r = q_next_node (config)) != 0) { struct call_args args; if (!bsy_test (&r->fa, F_BSY, config) || !bsy_test (&r->fa, F_CSY, config)) { char szDestAddr[FTN_ADDR_SZ + 1]; ftnaddress_to_str (szDestAddr, &r->fa); Log (4, "%s busy, skipping", szDestAddr); return 0; /* go to the next node */ } rel_grow_handles (6); threadsafe(++n_clients); lock_config_structure(config); args.node = r; args.config = config; if ((pid = branch (call, &args, sizeof (args))) < 0) { unlock_config_structure(config, 0); rel_grow_handles (-6); threadsafe(--n_clients); PostSem(&eothread); Log (1, "cannot branch out"); unblocksig(); SLEEP(1); blocksig(); check_child(&n_clients); } #if !defined(DEBUGCHILD) else { Log (5, "started client #%i, id=%i", n_clients, pid); #if defined(HAVE_FORK) && !defined(AMIGA) unlock_config_structure(config, 0); /* Forked child has own copy */ #endif } #endif } else { if (poll_flag) { if (n_clients <= 0 && q_not_empty (config) == 0) { Log (4, "the queue is empty, quitting..."); return -1; } } else config->q_present = 0; unblocksig(); SLEEP (config->rescan_delay); blocksig(); check_child(&n_clients); } } else { unblocksig(); SLEEP (config->call_delay); blocksig(); check_child(&n_clients); } return 0; }