From murphyn@maxx.mc.net Fri Jun 14 14:06:59 1996 Received: from po_box.cig.mot.com (po_box.cig.mot.com [136.182.15.5]) by orca.cig.mot.com (8.6.11/SCERG-1.12C) with ESMTP id OAA09762 for ; Fri, 14 Jun 1996 14:06:58 -0500 Message-Id: <199606141906.PAA12259@po_box.cig.mot.com> Received: from motgate2.mot.com ([129.188.136.20]) by pobox.mot.com (8.7.3/8.6.10/MOT-3.8) with ESMTP id OAA16301 for ; Fri, 14 Jun 1996 14:06:54 -0500 (CDT) Received: from maxx.mc.net (maxx.mc.net [206.138.8.7]) by motgate2.mot.com (8.7.3/8.6.10/MOT-3.8) with ESMTP id TAA17197 for ; Fri, 14 Jun 1996 19:04:58 GMT Received: (from murphyn@localhost) by maxx.mc.net (8.7.4/8.6.12) id OAA20654 for murphyn@cig.mot.com; Fri, 14 Jun 1996 14:00:36 -0500 (CDT) From: Neal Murphy Subject: alarm.c To: murphyn@cig.mot.com Date: Fri, 14 Jun 1996 14:00:36 -0500 (CDT) X-Mailer: ELM [version 2.4 PL25] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Status: RO /* Copyright 1996, Harsof Engineering. Please let me know of any errors in this code, so I can fix them. If you wish to use this module, send email to murphyn@mc.net. */ /* Date: 17 June 1996 Author: Neal P. Murphy Module Name: Alarm() for BeOS DR7 Required Headers: none Required Externs: extern unsigned int alarm(unsigned int) exterm void alarm_expired(void) Global Variables: none Global Functions: unsigned int alarm(unsigned int), void alarm_expired(void) Static Data: double time_started, thread_id alarm_thread, struct ALARM_STRUCT Local functions: long do_alarm(void *) Usage: time_remaining = alarm(seconds) alarm() works just as it is supposed to under Posix and Unix environments, with *one* exception. alarm() returns zero if the alarm was off, or it returns the time remaining 'till the alarm was to go off; this is true whether you are setting, stopping or re-setting the alarm clock. The exception is that your SIGALRM must include a call to alarm_expired(). Actually, DR7 doesn't require that one must call wait_for_thread(), but it is good form to do so anyway. Caveats: This function is *not* thread-safe. At some point I will produce a thread-safe version, but for now, this is all there is. */ #include #include #include #include struct ALARM_STRUCT { thread_id thread; unsigned int time; }; static double time_started = 0.0; static thread_id alarm_thread = -1; static struct ALARM_STRUCT alarm_struct; static long do_alarm (void *); void alarm_expired (void); /* This should mimic the Unix/Posix alarm() function well enough, with the caveat that one's SIGALRM handler must call alarm_expired() to wait for the alarm thread to finish. */ unsigned int alarm (unsigned int seconds) { unsigned int time_left = 0; /* If an alarm is active, turn it off, saving the remaining time */ if (alarm_thread != -1) { /* We'll be generous and count partial seconds as whole seconds. */ time_left = alarm_struct.time - (unsigned int) ((system_time () - time_started) / 1000000.0); /* Kill the alarm thread, since we think it's still there */ kill_thread (alarm_thread); /* We need to clean up as though the alarm occured. */ alarm_expired (); time_started = 0, 0; alarm_struct.thread = -1; alarm_struct.time = 0; } /* This was confusing. Linux appears to used signed int, while SunOS ans SysV/88 use unsigned. I will use unsigned. */ /* Set a new alarm clock, if requested. */ if (seconds > 0) { alarm_struct.thread = find_thread (NULL); alarm_struct.time = seconds; time_started = system_time (); alarm_thread = spawn_thread (do_alarm, "alarm_thread", B_NORMAL_PRIORITY, (void *) &alarm_struct); resume_thread (alarm_thread); } /* Now return [unused time | 0] */ return ((unsigned int) time_left); } /* This function is the departure from Unix/Posix alarm handling. In the case of Be's missing alarm() function, this stuff needs to be done in the SIGALRM handler. When Be implements alarm(), this function call can be eliminated from user's SIGALRM signal handlers. Technically, under DR7, one really doesn't need wait_for_thread(), but it is good form to use it anyway. */ void alarm_expired (void) { long ret_val; if (alarm_thread != -1) { wait_for_thread (alarm_thread, &ret_val); alarm_thread = -1; } } /* This is the function that snoozes the requisite number of seconds and then SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be uses thread_id; currently they are both typdef'ed as long, but I'll do the cast anyway. */ static long do_alarm (void *alarm_struct) { snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0); kill ((pid_t) ((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM); time_started = 0; ((struct ALARM_STRUCT *)alarm_struct)->thread = -1; ((struct ALARM_STRUCT *)alarm_struct)->time = 0; } .