Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
ISC Open Source Projects
BIND
Commits
94123b51
Commit
94123b51
authored
Aug 19, 1998
by
Bob Halley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
checkpoint
parent
dcd83f0e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
186 additions
and
143 deletions
+186
-143
bin/tests/task_test.c
bin/tests/task_test.c
+52
-23
lib/isc/include/isc/task.h
lib/isc/include/isc/task.h
+21
-66
lib/isc/pthreads/include/isc/condition.h
lib/isc/pthreads/include/isc/condition.h
+7
-0
lib/isc/pthreads/include/isc/thread.h
lib/isc/pthreads/include/isc/thread.h
+1
-0
lib/isc/task.c
lib/isc/task.c
+105
-54
No files found.
bin/tests/task_test.c
View file @
94123b51
...
...
@@ -10,12 +10,14 @@
#include <isc/thread.h>
mem_context_t
mctx
=
NULL
;
os_mutex_t
timer_lock
;
os_condition_t
timer_wakeup
;
/*ARGSUSED*/
static
boolean_t
my_callback
(
task_t
__attribute__
((
unused
))
task
,
void
*
arg
,
generic
_event_t
__attribute__
((
unused
))
event
)
task
_event_t
__attribute__
((
unused
))
event
)
{
int
i
,
j
;
char
*
name
=
arg
;
...
...
@@ -32,7 +34,7 @@ my_callback(task_t __attribute__((unused)) task,
static
boolean_t
my_shutdown
(
task_t
__attribute__
((
unused
))
task
,
void
*
arg
,
generic
_event_t
__attribute__
((
unused
))
event
)
task
_event_t
__attribute__
((
unused
))
event
)
{
char
*
name
=
arg
;
...
...
@@ -44,7 +46,7 @@ my_shutdown(task_t __attribute__((unused)) task,
static
boolean_t
my_tick
(
task_t
__attribute__
((
unused
))
task
,
void
*
arg
,
generic
_event_t
__attribute__
((
unused
))
event
)
task
_event_t
__attribute__
((
unused
))
event
)
{
char
*
name
=
arg
;
...
...
@@ -52,16 +54,41 @@ my_tick(task_t __attribute__((unused)) task,
return
(
FALSE
);
}
/*ARGSUSED*/
static
boolean_t
wakeup_timer
(
task_t
__attribute__
((
unused
))
task
,
void
*
arg
,
task_event_t
__attribute__
((
unused
))
event
)
{
printf
(
"wakeup timer
\n
"
);
(
void
)
os_condition_broadcast
(
&
timer_wakeup
);
return
(
FALSE
);
}
void
*
simple_timer_run
(
void
*
arg
)
{
task_t
task
=
arg
;
generic
_event_t
event
;
task
_event_t
event
;
int
i
;
struct
timespec
ts
;
struct
timeval
tv
;
struct
timeval
tv1
;
boolean_t
timeout
;
for
(
i
=
0
;
i
<
10
;
i
++
)
{
sleep
(
1
);
for
(
i
=
0
;
i
<
5
;
i
++
)
{
(
void
)
gettimeofday
(
&
tv
,
NULL
);
ts
.
tv_sec
=
tv
.
tv_sec
+
5
;
ts
.
tv_nsec
=
0
;
(
void
)
os_mutex_lock
(
&
timer_lock
);
(
void
)
os_condition_waituntil
(
&
timer_wakeup
,
&
timer_lock
,
&
ts
,
&
timeout
);
(
void
)
os_mutex_unlock
(
&
timer_lock
);
(
void
)
gettimeofday
(
&
tv1
,
NULL
);
printf
(
"slept %d secs
\n
"
,
tv1
.
tv_sec
-
tv
.
tv_sec
);
if
(
timeout
)
printf
(
"timer timeout
\n
"
);
printf
(
"sending timer to %p
\n
"
,
task
);
event
=
event_
get
(
mctx
,
2
,
my_tick
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
2
,
my_tick
,
NULL
,
sizeof
*
event
);
INSIST
(
event
!=
NULL
);
(
void
)
task_send_event
(
task
,
&
event
);
}
...
...
@@ -77,6 +104,8 @@ simple_timer_init(task_t task) {
task_clone
=
NULL
;
task_attach
(
task
,
&
task_clone
);
(
void
)
os_mutex_init
(
&
timer_lock
);
(
void
)
os_condition_init
(
&
timer_wakeup
);
INSIST
(
os_thread_create
(
simple_timer_run
,
task_clone
,
&
t
));
(
void
)
os_thread_detach
(
t
);
}
...
...
@@ -86,7 +115,7 @@ main(int argc, char *argv[]) {
task_manager_t
manager
=
NULL
;
task_t
t1
=
NULL
,
t2
=
NULL
;
task_t
t3
=
NULL
,
t4
=
NULL
;
generic
_event_t
event
;
task
_event_t
event
;
unsigned
int
workers
;
if
(
argc
>
1
)
...
...
@@ -110,35 +139,35 @@ main(int argc, char *argv[]) {
printf
(
"task 2 = %p
\n
"
,
t2
);
sleep
(
2
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
wakeup_timer
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t1
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t2
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t3
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t4
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t2
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t3
,
&
event
);
event
=
event_
get
(
mctx
,
1
,
my_callback
,
sizeof
*
event
);
event
=
task_
event_
allocate
(
mctx
,
1
,
my_callback
,
NULL
,
sizeof
*
event
);
task_send_event
(
t4
,
&
event
);
task_detach
(
&
t1
);
...
...
lib/isc/include/isc/task.h
View file @
94123b51
...
...
@@ -16,7 +16,7 @@
*** Core Types.
***/
typedef
struct
generic
_event
*
generic
_event_t
;
typedef
struct
task
_event
*
task
_event_t
;
typedef
struct
task
*
task_t
;
typedef
struct
task_manager
*
task_manager_t
;
...
...
@@ -28,99 +28,54 @@ typedef struct task_manager * task_manager_t;
/*
* Negative event types are reserved for use by the task manager.
*/
typedef
int
event
_
type_t
;
typedef
int
task_
eventtype_t
;
typedef
boolean_t
(
*
event
_action_t
)(
task_t
,
void
*
,
generic
_event_t
);
typedef
boolean_t
(
*
task
_action_t
)(
task_t
,
void
*
,
task
_event_t
);
/*
* Unlike other type names, which are prefixed with the module's name,
* event types have a suffix of "_event_t". All event types must start
* with the same fields as the generic event.
*/
struct
generic_event
{
* This structure is public because "subclassing" it may be useful when
* defining new event types.
*/
struct
task_event
{
mem_context_t
mctx
;
size_t
size
;
event_type_t
type
;
event_action_t
action
;
LINK
(
struct
generic_event
)
link
;
task_eventtype_t
type
;
task_action_t
action
;
void
*
arg
;
LINK
(
struct
task_event
)
link
;
};
#define TASK_NOP_EVENT (-1)
typedef
generic_event_t
nop_event_t
;
typedef
LIST
(
struct
generic_event
)
event_list_t
;
typedef
LIST
(
struct
task_event
)
task_eventlist_t
;
generic_event_t
event_get
(
mem_context_t
,
event_type_t
,
event_action_t
,
size_t
);
void
event_put
(
generic_event_t
*
);
task_event_t
task_event_allocate
(
mem_context_t
,
task_eventtype_t
,
task_action_t
,
void
*
arg
,
size_t
);
void
task_event_free
(
task_event_t
*
);
/***
*** Tasks.
***/
typedef
enum
{
task_state_idle
,
task_state_ready
,
task_state_running
,
task_state_shutdown
}
task_state_t
;
#define TASK_MAGIC 0x5441534BU
/* TASK. */
struct
task
{
/* Not locked. */
unsigned
int
magic
;
struct
task_manager
*
manager
;
os_mutex_t
lock
;
/* Locked by task lock. */
task_state_t
state
;
unsigned
int
references
;
event_list_t
events
;
unsigned
int
quantum
;
boolean_t
shutdown_pending
;
event_action_t
shutdown_action
;
void
*
arg
;
/* Locked by task manager lock. */
LINK
(
struct
task
)
link
;
LINK
(
struct
task
)
ready_link
;
};
boolean_t
task_create
(
task_manager_t
,
void
*
,
event
_action_t
,
task
_action_t
,
unsigned
int
,
task_t
*
);
void
task_attach
(
task_t
,
task_t
*
);
void
task_detach
(
task_t
*
);
boolean_t
task_send_event
(
task_t
,
generic
_event_t
*
);
task
_event_t
*
);
void
task_shutdown
(
task_t
);
void
task_destroy
(
task_t
*
);
/***
*** Task Manager.
***/
#define TASK_MANAGER_MAGIC 0x54534B4DU
/* TSKM. */
struct
task_manager
{
/* Not locked. */
unsigned
int
magic
;
mem_context_t
mctx
;
os_mutex_t
lock
;
/* Locked by task manager lock. */
unsigned
int
default_quantum
;
LIST
(
struct
task
)
tasks
;
LIST
(
struct
task
)
ready_tasks
;
os_condition_t
work_available
;
boolean_t
exiting
;
unsigned
int
workers
;
os_condition_t
no_workers
;
};
unsigned
int
task_manager_create
(
mem_context_t
,
unsigned
int
,
unsigned
int
,
...
...
lib/isc/pthreads/include/isc/condition.h
View file @
94123b51
...
...
@@ -3,6 +3,9 @@
#define CONDITION_H 1
#include <pthread.h>
#include <errno.h>
#include <isc/boolean.h>
#include <isc/assertions.h>
typedef
pthread_cond_t
os_condition_t
;
...
...
@@ -10,6 +13,10 @@ typedef pthread_cond_t os_condition_t;
#define os_condition_init(cp) (pthread_cond_init((cp), NULL) == 0)
#define os_condition_wait(cp, mp) (pthread_cond_wait((cp), (mp)) == 0)
#define os_condition_waituntil(cp, mp, tsp, top) \
(pthread_cond_timedwait((cp), (mp), (tsp)) == 0 \
? TRUE \
: ((*(top) = (errno == ETIMEDOUT)), FALSE))
#define os_condition_signal(cp) (pthread_cond_signal((cp)) == 0)
#define os_condition_broadcast(cp) (pthread_cond_broadcast((cp)) == 0)
#define os_condition_destroy(cp) (pthread_cond_destroy((cp)) == 0)
...
...
lib/isc/pthreads/include/isc/thread.h
View file @
94123b51
...
...
@@ -11,5 +11,6 @@ typedef pthread_t os_thread_t;
#define os_thread_create(s, a, tp) (pthread_create((tp), NULL, (s), (a)) \
== 0)
#define os_thread_detach(t) (pthread_detach((t)) == 0)
#define os_thread_self pthread_self
#endif
/* THREAD_H */
lib/isc/task.c
View file @
94123b51
...
...
@@ -6,10 +6,10 @@
#include <isc/thread.h>
#include <isc/task.h>
#define VALID_MANAGER(m) ((m) != NULL && \
(m)->magic == TASK_MANAGER_MAGIC)
#define VALID_TASK(t) ((t) != NULL && \
(t)->magic == TASK_MAGIC)
/***
*** General Macros.
***/
/*
* We use macros instead of calling the os_ routines directly because
...
...
@@ -23,56 +23,65 @@
#define WAIT(cvp, lp) INSIST(os_condition_wait((cvp), (lp)))
#define BROADCAST(cvp) INSIST(os_condition_broadcast((cvp)))
#define DEFAULT_DEFAULT_QUANTUM 5
#define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks))
#ifdef DEBUGTRACE
#define XTRACE(m) printf("%s %p\n", (m),
p
thread_self())
#define XTRACE(m)
printf("%s %p\n", (m),
os_
thread_self())
#else
#define XTRACE(m)
#endif
/***
*** T
ask
s.
*** T
ype
s.
***/
generic_event_t
event_get
(
mem_context_t
mctx
,
event_type_t
type
,
event_action_t
action
,
size_t
size
)
{
generic_event_t
event
;
if
(
size
<
sizeof
*
event
)
return
(
NULL
);
if
(
type
<
0
)
return
(
NULL
);
if
(
action
==
NULL
)
return
(
NULL
);
event
=
mem_get
(
mctx
,
size
);
if
(
event
==
NULL
)
return
(
NULL
);
event
->
mctx
=
mctx
;
event
->
size
=
size
;
event
->
type
=
type
;
event
->
action
=
action
;
return
(
event
);
}
void
event_put
(
generic_event_t
*
eventp
)
{
generic_event_t
event
;
REQUIRE
(
eventp
!=
NULL
);
event
=
*
eventp
;
REQUIRE
(
event
!=
NULL
);
mem_put
(
event
->
mctx
,
event
,
event
->
size
);
*
eventp
=
NULL
;
}
typedef
enum
{
task_state_idle
,
task_state_ready
,
task_state_running
,
task_state_shutdown
}
task_state_t
;
#define TASK_MAGIC 0x5441534BU
/* TASK. */
#define VALID_TASK(t) ((t) != NULL && \
(t)->magic == TASK_MAGIC)
struct
task
{
/* Not locked. */
unsigned
int
magic
;
task_manager_t
manager
;
os_mutex_t
lock
;
/* Locked by task lock. */
task_state_t
state
;
unsigned
int
references
;
task_eventlist_t
events
;
unsigned
int
quantum
;
boolean_t
shutdown_pending
;
task_action_t
shutdown_action
;
void
*
arg
;
/* Locked by task manager lock. */
LINK
(
struct
task
)
link
;
LINK
(
struct
task
)
ready_link
;
};
#define TASK_MANAGER_MAGIC 0x54534B4DU
/* TSKM. */
#define VALID_MANAGER(m) ((m) != NULL && \
(m)->magic == TASK_MANAGER_MAGIC)
struct
task_manager
{
/* Not locked. */
unsigned
int
magic
;
mem_context_t
mctx
;
os_mutex_t
lock
;
/* Locked by task manager lock. */
unsigned
int
default_quantum
;
LIST
(
struct
task
)
tasks
;
LIST
(
struct
task
)
ready_tasks
;
os_condition_t
work_available
;
boolean_t
exiting
;
unsigned
int
workers
;
os_condition_t
no_workers
;
};
#define DEFAULT_DEFAULT_QUANTUM 5
#define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks))
/***
*** Tasks.
...
...
@@ -104,7 +113,7 @@ task_free(task_t task) {
boolean_t
task_create
(
task_manager_t
manager
,
void
*
arg
,
event
_action_t
shutdown_action
,
unsigned
int
quantum
,
task
_action_t
shutdown_action
,
unsigned
int
quantum
,
task_t
*
taskp
)
{
task_t
task
;
...
...
@@ -186,10 +195,10 @@ task_detach(task_t *taskp) {
}
boolean_t
task_send_event
(
task_t
task
,
generic
_event_t
*
eventp
)
{
task_send_event
(
task_t
task
,
task
_event_t
*
eventp
)
{
boolean_t
was_idle
=
FALSE
;
boolean_t
discard
=
FALSE
;
generic
_event_t
event
;
task
_event_t
event
;
REQUIRE
(
VALID_TASK
(
task
));
REQUIRE
(
eventp
!=
NULL
);
...
...
@@ -217,7 +226,7 @@ task_send_event(task_t task, generic_event_t *eventp) {
UNLOCK
(
&
task
->
lock
);
if
(
discard
)
{
event_
put
(
&
event
);
task_
event_
free
(
&
event
);
*
eventp
=
NULL
;
return
(
TRUE
);
}
...
...
@@ -412,9 +421,9 @@ void *task_manager_run(void *uap) {
boolean_t
wants_shutdown
;
boolean_t
free_task
=
FALSE
;
void
*
arg
;
event
_action_t
action
;
generic
_event_t
event
;
event
_
list_t
remaining_events
;
task
_action_t
action
;
task
_event_t
event
;
task_
eventlist_t
remaining_events
;
boolean_t
discard_remaining
=
FALSE
;
INSIST
(
VALID_TASK
(
task
));
...
...
@@ -466,7 +475,7 @@ void *task_manager_run(void *uap) {
* callback returned.
*/
if
(
event
!=
NULL
)
event_
put
(
&
event
);
task_
event_
free
(
&
event
);
else
wants_shutdown
=
TRUE
;
...
...
@@ -522,13 +531,13 @@ void *task_manager_run(void *uap) {
UNLOCK
(
&
task
->
lock
);
if
(
discard_remaining
)
{
generic
_event_t
next_event
;
task
_event_t
next_event
;
for
(
event
=
HEAD
(
remaining_events
);
event
!=
NULL
;
event
=
next_event
)
{
next_event
=
NEXT
(
event
,
link
);
event_
put
(
&
event
);
task_
event_
free
(
&
event
);
}
}
...
...
@@ -714,3 +723,45 @@ task_manager_destroy(task_manager_t *managerp) {
*
managerp
=
NULL
;
}
/***
*** Events.
***/
task_event_t
task_event_allocate
(
mem_context_t
mctx
,
task_eventtype_t
type
,
task_action_t
action
,
void
*
arg
,
size_t
size
)
{
task_event_t
event
;
if
(
size
<
sizeof
*
event
)
return
(
NULL
);
if
(
type
<
0
)
return
(
NULL
);
if
(
action
==
NULL
)
return
(
NULL
);
event
=
mem_get
(
mctx
,
size
);
if
(
event
==
NULL
)
return
(
NULL
);
event
->
mctx
=
mctx
;
event
->
size
=
size
;
event
->
type
=
type
;
event
->
action
=
action
;
event
->
arg
=
arg
;
return
(
event
);
}
void
task_event_free
(
task_event_t
*
eventp
)
{
task_event_t
event
;
REQUIRE
(
eventp
!=
NULL
);
event
=
*
eventp
;
REQUIRE
(
event
!=
NULL
);
mem_put
(
event
->
mctx
,
event
,
event
->
size
);
*
eventp
=
NULL
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment