1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
/*
* This software is Copyright 1989 by Jack Hudler.
*
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
* use this software as long as: there is no monetary profit gained
* specifically from the use or reproduction or this software, it is not
* sold, rented, traded or otherwise marketed, and this copyright notice is
* included prominently in any copy made.
*
* The author make no claims as to the fitness or correctness of this software
* for any use whatsoever, and it is provided as is. Any use of this software
* is at the user's own risk.
*
*/
/****************************** Module Header ******************************\
* Module Name: alarm.c
* Created : 11-08-89
* Author : Jack Hudler [jack@csccat.lonestar.org]
* Copyright : 1988 Jack Hudler.
* Function : Unix like alarm signal simulator.
\***************************************************************************/
/* Tested using OS2 1.2 with Microsoft C 5.1 and 6.0. */
#define INCL_DOSPROCESS
#define INCL_DOSSIGNALS
#define INCL_DOS
#include <os2.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include "alarm.h"
#define ALARM_STACK 4096 /* This maybe over kill, but the page size is 4K */
static PBYTE pbAlarmStack;
static SEL selAlarmStack;
static TID tidAlarm;
static PID pidMain;
static BOOL bAlarmInit=FALSE;
static BOOL bAlarmRunning=FALSE;
static USHORT uTime;
static VOID FAR alarm_thread ( VOID )
{
while(1)
{
if (bAlarmRunning)
{
DosSleep(1000L);
uTime--;
if (uTime==0L)
{
// send signal to the main process.. I could have put raise() here
// however that would require the use of the multithreaded library,
// and it does not contain raise()!
// I tried it with the standard library, this signaled ok, but a
// test printf in the signal would not work and even caused SEGV.
// So I signal the process through OS/2 and then the process
// signals itself.
if (bAlarmRunning)
DosFlagProcess(pidMain,FLGP_PID, PFLG_A,1);
bAlarmRunning=FALSE;
}
}
else
DosSleep(500L);
}
}
static VOID PASCAL FAR AlarmSignal(USHORT usSigArg,USHORT usSigNum)
{
/*
* this is not executed from the thread. The thread triggers Process
* flag A which is in the main processes scope, this inturn triggers
* (via the raise) SIGUSR1 which is defined to SIGALRM.
*/
raise(SIGUSR1);
}
static void alarm_init(void)
{
PFNSIGHANDLER pfnPrev;
USHORT pfAction;
PIDINFO pid;
bAlarmInit = TRUE;
if (!DosAllocSeg( ALARM_STACK, (PSEL) &selAlarmStack, SEG_NONSHARED ))
{
OFFSETOF(pbAlarmStack) = ALARM_STACK - 2;
SELECTOROF(pbAlarmStack) = selAlarmStack;
/* Create the thread */
if (DosCreateThread( alarm_thread, &tidAlarm, pbAlarmStack ))
{
fprintf(stderr,"Alarm thread failed to start.\n");
exit(1);
}
/* Setup the signal handler for Process Flag A */
if (DosSetSigHandler(AlarmSignal,&pfnPrev,&pfAction,SIGA_ACCEPT,SIG_PFLG_A))
{
fprintf(stderr,"SigHandler Failed to install.\n");
exit(1);
}
/* Save main process ID, we'll need it for triggering the signal */
DosGetPID(&pid);
pidMain = pid.pid;
}
else
exit(1);
}
unsigned alarm(unsigned sec)
{
if (!bAlarmInit) alarm_init();
if (sec)
{
uTime = sec;
bAlarmRunning = TRUE;
}
else
bAlarmRunning = FALSE;
return 0;
}
#ifdef TESTING
/* A simple test to see if it works */
BOOL x;
void timeout(void)
{
fprintf(stderr,"ALARM TRIGGERED!!\n");
DosBeep(1000,500);
x++;
}
void main(void)
{
(void) signal(SIGALRM, timeout);
(void) alarm(1L);
printf("ALARM RUNNING!!\n");
while(!x);
}
#endif
|