1ggAddTask(3)                          GGI                         ggAddTask(3)
2
3
4

NAME

6       ggAddTask,       ggDelTask,      ggTimeBase,      GG_SCHED_TICKS2USECS,
7       GG_SCHED_USECS2TICKS : LibGG simple task scheduler routines
8

SYNOPSIS

10       #include <ggi/gg.h>
11
12       struct gg_task {
13             gg_task_callback_fn     *cb;    /* Function to call to run task      */
14             void                    *hook;  /* Task data can be hung here        */
15             int                     pticks; /* Run once every pticks ticks.      */
16             int                     ncalls; /* Run ncalls times (0 = infinite)   */
17             int                     lasttick; /* last tick run (read-only)       */
18
19             /* Other members present but are for internal use only. */
20       };
21
22       typedef int (gg_task_callback_fn)(struct gg_task *task);
23
24       GG_SCHED_TICKS2USECS(uint32_t ticks);
25       GG_SCHED_USECS2TICKS(uint32_t usecs);
26
27       uint32_t ggTimeBase(void);
28
29       int ggAddTask(struct gg_task *task);
30
31       int ggDelTask(struct gg_task *task);
32
33

DESCRIPTION

35       LibGG implements a task scheduler in  both  threaded  and  non-threaded
36       environments.  Tasks can be registered with the scheduler to run short,
37       asynchronous routines called "handlers" which may interrupt or  run  in
38       parallel  with  the  normal  flow-of-control.  It is recommended to use
39       LibGG tasks in lieue of threads when writing for  maximum  portability,
40       if they can meet the demands of the application, since not all environ‐
41       ments support threads.
42
43       The LibGG task scheduler uses a unit of time called a "tick", which may
44       vary  between architectures.  The tick is guaranteed to be no more than
45       one second, however, most environments will support at least  60  ticks
46       per  second.  By default LibGG will select 60 ticks per second if it is
47       supported, see below for instructions on modifying this behavior.   The
48       function ggTimeBase is used to find out the size of a tick.
49
50       GG_SCHED_TICKS2USECS  and  GG_SCHED_USECS2TICKS  are  convenient macros
51       that simplifies conversion between  ticks  and  microseconds  and  vice
52       versa.
53
54       The  maximum  rate  at  which a periodic task may run is once per tick.
55       The maximum period (minimum rate) of a LibGG task is the value  of  the
56       macro GG_SCHED_TICK_WRAP minus one, and is also measured in ticks.
57
58       ggAddTask will examine the values in the offered task control structure
59       task.  Before calling ggAddTask the task control structure must be ini‐
60       tialized  by  filling  it  with  zeros, including the internal-use-only
61       area.  The task control structure should be further initialized by pro‐
62       viding  at least a pointer to a callback handler function in the member
63       cb, and initializing the pticks member to contain the number  of  ticks
64       between  each  call  to the handler function.  The ncalls member may be
65       left at zero, in which case the task  remains  scheduled  to  run  once
66       every  pticks  until explicitly deleted, or it may be set to a positive
67       integer to indicate that the task should be automatically deleted after
68       the  handler  has  been called ncalls times. The int return type on the
69       callback hook is only there for  possible  future  expansion.  For  now
70       callbacks should always return 0. Other values are undefined.
71
72       The  task  control  structure must only be used for one task, however a
73       task handler may be called by multiple tasks.  The member hook is  pro‐
74       vided  for  the  application's  use  in the task control structure as a
75       means to easily transport task-local data to the handler.   If  a  tick
76       arrives  during  a call to ggAddTask, the handler may be invoked before
77       ggAddTask returns; A memory barrier  is  included  in  ggAddTask  which
78       ensures that all values in the task control structure are up to date on
79       multiprocessor systems even in this case.  The task  control  structure
80       should  not  be altered, except by a task handler as noted below, while
81       the task is scheduled.
82
83       ggDelTask will remove a task from  the  scheduler.   The  task  may  be
84       called  after  ggDelTask  is called, but is guaranteed not to be called
85       after ggDelTask has returned, until such a point as it is  added  again
86       with ggAddTask.
87
88       A task can be put to sleep for a certain amount of time in microseconds
89       by altering the period of the task to the correct number of ticks,  and
90       then  that  task  itself can reset it's period back based on a value in
91       it's private hook when it next runs.
92
93       A task can wait for an other task to finish either by writing  code  to
94       poll  the  other task's flags, or by writing a callback into the latter
95       task when it is done to reschedule a list of waiting tasks.  How a task
96       terminates is entirely up to the author.
97
98       Each  scheduled  task is guaranteed never to be reentered by the sched‐
99       uler.  That is, only one call to a task handler for a given  task  con‐
100       trol  structure will be run at a time, though a single handler function
101       that handles more than one task control structure may be entered simul‐
102       taneously once per structure.
103
104       When  a  task  executes,  the handler is invoked and the parameter task
105       given to the handler contains the same pointer value as  was  given  to
106       ggAddTask.   The ncalls member will be updated to contain the number of
107       calls, including the current call, which  remain  before  the  task  is
108       automatically  deleted (or zero if the task will never be automatically
109       deleted.)  Thus it is safe to call ggAddTask again to  reuse  the  task
110       control structure once the handler has returned with ncalls equal to 1.
111       The lasttick member will contain the number of the LibGG scheduler tick
112       being  executed,  which  should increase monotonically unless a problem
113       occurs  as   noted   below,   wrapping   around   modulus   the   value
114       GG_SCHED_TICK_WRAP.
115
116       ggAddTask  and  ggDelTask may not be called from within a task handler,
117       however, the task handler is free to alter the pticks and  ncalls  mem‐
118       bers  in the task control structure task in order to change its period,
119       or increase or decrease the number of calls before auto-deletion.   For
120       example,  to  cancel  itself,  a  task need only set ncalls to 1 before
121       returning.  The task handler may also change it's callback function  or
122       data hook members.  A write memory barrier is included in the scheduler
123       to prevent old values from being seen by other processors on  SMP  sys‐
124       tems.
125
126       LibGG  ticks  are  measured  in  real (wall clock) time and LibGG makes
127       every effort to ensure that drift due to runtime factors is kept  at  a
128       minimum.   When  a  process is suspended, however, LibGG ticks stop and
129       resume where they left off.  Likewise, when system utilization is  very
130       high  or tasks are misused the LibGG scheduler may fail to count ticks.
131       However the ggCurTime(3) function will still be accurate in these cases
132       and can be used to detect such situations.
133
134       All  scheduled LibGG tasks may in the worst case have to be run serial‐
135       ized, and may be postponed  slightly  while  a  call  to  ggAddTask  or
136       ggDelTask  is in progress, so there may be some delay between the start
137       of a LibGG tick and the actual execution of the task.  This can be min‐
138       imized  by  limiting  the  duties of task handlers to very short, quick
139       operations.
140
141       When utilization is high or tasks misbehave, the  scheduler  may  elect
142       simply  not  to  call  a task handler even though it is scheduled to be
143       called on a given tick.  This may happen either  to  all  tasks  or  to
144       select  individual  tasks.    The "lasttick" member of the task control
145       structure can be safely read from within a task  handler  in  order  to
146       detect  such  a  circumstance (it will always contain the current tick,
147       but can be compared to a previously stored value.)
148
149       Since LibGG tasks may be called in a signal handler or other non-inter‐
150       ruptible  context, they should not call ggLock(3) on any locks that may
151       already be locked.  In addition, there may be  limits  imposed  on  the
152       functions  which  are  safe  to use inside task handlers (that is, only
153       reentrant functions may be safe.)  More detailed information  on  using
154       locks  inside  LibGG  task  handlers  is  contained  in the manpage for
155       ggLock(3).
156
157       Scheduled tasks will be canceled, in a somewhat precarious fashion,  by
158       a normal call to ggExit(3).  As such, it is considered best practice to
159       use ggDelTask to cancel tasks when gracefully deinitializing LibGG or a
160       library that uses LibGG.
161

RETURN VALUE

163       ggAddTask returns GGI_OK on success or:
164
165       ·   GGI_EARGREQ if called with NULL argument;
166
167       ·   GGI_EARGINVAL if the task is incorrectly set;
168
169       ·   GGI_EBUSY if the task is already added;
170
171       ·   GGI_ENOMEM if the task lock could not be created.
172
173       ggDelTask returns  GGI_OK on success or:
174
175       ·   GGI_EARGREQ if called with NULL argument;
176
177       ·   GGI_EARGINVAL if the task is not currently scheduled.
178
179       ggTimeBase  returns  an integer between 1 and 1000000, inclusive, which
180       represents the number on microseconds between each tick  of  the  LibGG
181       scheduler.
182

ENVIRONMENT VARIABLES

184       If  the  "-schedhz=speed"  option is present in the GG_OPTS environment
185       variable when ggInit is first called, the scheduler time base  will  be
186       set  such  that the scheduler executes speed ticks per second.  If this
187       is not possible, ggInit(3) will fail.  The default speed  is  60HZ,  or
188       the maximum that the environment can support, whichever is less.
189
190       If  the  "-signum=n" option is present in the GG_OPTS environment vari‐
191       able when ggInit is first  called,  and  LibGG  is  not  compiled  with
192       threads support, the UNIX signal used by the scheduler may be selected.
193       If n is not a valid signal for this purpose, the results are undefined,
194       but  should  not be unsafe for SUID processes.  The default signal used
195       is usually SIGPROF, but may be chosen differently based on the needs of
196       the package maintainer for any particular LibGG distribution.  Applica‐
197       tions using LibGG are forbidden from using this signal for  other  pur‐
198       poses, whether or not tasks are used.
199
200       If  the  "-schedthreads=numthreads"  option  is  present in the GG_OPTS
201       environment variable when ggInit is first called, and LibGG is compiled
202       with threading support, the scheduler will create numthreads additional
203       threads to call task handlers.  The default is one  additional  thread.
204       If  numthreads is not valid or causes resource allocation problems, the
205       results are undefined, but should not be unsafe for SUID (or other ele‐
206       vated privilege) processes.
207
208
209
210libgg-1.0.x                       2005-08-26                      ggAddTask(3)
Impressum