Annotation of wikisrc/projects/project/kernel_continuations.mdwn, revision 1.4
1.1 jmmv 1: [[!template id=project
2:
3: title="Kernel continuations"
4:
5: contact="""
6: [tech-kern](mailto:tech-kern@NetBSD.org),
7: [board](mailto:board@NetBSD.org),
8: [core](mailto:core@NetBSD.org)
9: """
10:
11: category="kernel"
12: difficulty="hard"
13:
14: description="""
1.4 ! riastrad 15: This project proposal is a subtask of [[smp_networking]].
1.1 jmmv 16:
17: The goal of this project is to implement continuations at the kernel level.
18: Most of the pieces are already available in the kernel, so this can be
19: reworded as: combine *callouts*, *softints*, and *workqueues* into a single
1.2 plunky 20: framework. Continuations are meant to be cheap; very cheap.
1.1 jmmv 21:
1.3 dholland 22: These continuations are a dispatching system for making callbacks at
23: scheduled times or in different thread/interrupt contexts.
24: They aren't "continuations" in the usual sense such as you might find
25: in Scheme code.
26:
1.1 jmmv 27: Please note that the main goal of this project is to simplify the
28: implementation of [[SMP networking|smp_networking]], so care must be taken
29: in the design of the interface to support all the features required for
30: this other project.
31:
32: The proposed interface looks like the following. This interface is mostly
33: derived from the `callout(9)` API and is a superset of the softint(9) API.
34: The most significant change is that workqueue items are not tied to a
35: specific kernel thread.
36:
37: * `kcont_t *kcont_create(kcont_wq_t *wq, kmutex_t *lock, void
38: (*func)(void *, kcont_t *), void *arg, int flags);`
39:
40: A `wq` must be supplied. It may be one returned by
41: `kcont_workqueue_acquire` or a predefined workqueue such as (sorted from
42: highest priority to lowest):
43:
44: * `wq_softserial`, `wq_softnet`, `wq_softbio`, `wq_softclock`
45: * `wq_prihigh`, `wq_primedhigh`, `wq_primedlow`, `wq_prilow`
46:
47: `lock`, if non-NULL, should be locked before calling `func(arg)` and
48: released afterwards. However, if the lock is released and/or destroyed
49: before the called function returns, then, before returning,
50: `kcont_set_mutex` must be called with either a new mutex to be released
51: or `NULL`. If acquiring lock would block, other pending kernel
52: continuations which depend on other locks may be dispatched in the
53: meantime. However, all continuations sharing the same set of `{ wq, lock,
54: [ci] }` need to be processed in the order they were scheduled.
55:
56: `flags` must be 0. This field is just provided for extensibility.
57:
58: * `int kcont_schedule(kcont_t *kc, struct cpu_info *ci, int nticks);`
59:
60: If the continuation is marked as *INVOKING*, an error of `EBUSY` should
61: be returned. If `nticks` is 0, the continuation is marked as *INVOKING*
62: while *EXPIRED* and *PENDING* are cleared, and the continuation is
63: scheduled to be invoked without delay. Otherwise, the continuation is
64: marked as *PENDING* while *EXPIRED* status is cleared, and the timer
65: reset to `nticks`. Once the timer expires, the continuation is marked as
66: *EXPIRED* and *INVOKING*, and the *PENDING* status is cleared. If `ci`
67: is non-NULL, the continuation is invoked on the specified CPU if the
68: continuations's workqueue has per-cpu queues. If that workqueue does not
69: provide per-cpu queues, an error of `ENOENT` is returned. Otherwise when
70: `ci` is `NULL`, the continuation is invoked on either the current CPU or
71: the next available CPU depending on whether the continuation's workqueue
72: has per-cpu queues or not, respectively.
73:
74: * `void kcont_destroy(kcont_t *kc);`
75:
76: * `kmutex_t *kcont_getmutex(kcont_t *kc);`
77:
78: Returns the lock currently associated with the continuation `kc`.
79:
80: * `void kcont_setarg(kcont_t *kc, void *arg);`
81:
82: Updates `arg` in the continuation `kc`. If no lock is associated with
83: the continuation, then `arg` may be changed at any time; however, if the
84: continuation is being invoked, it may not pick up the change. Otherwise,
85: `kcont_setarg` must only be called when the associated lock is locked.
86:
87: * `kmutex_t *kcont_setmutex(kcont_t *kc, kmutex_t *lock);`
88:
89: Updates the lock associated with the continuation `kc` and returns the
90: previous lock. If no lock is currently associated with the continuation,
91: then calling this function with a lock other than NULL will trigger an
92: assertion failure. Otherwise, `kcont_setmutex` must be called only when
93: the existing lock (which will be replaced) is locked. If
94: `kcont_setmutex` is called as a result of the invokation of func, then
95: after kcont_setmutex has been called but before func returns, the
96: replaced lock must have been released, and the replacement lock, if
97: non-NULL, must be locked upon return.
98:
99: * `void kcont_setfunc(kcont_t *kc, void (*func)(void *), void *arg);`
100:
101: Updates `func` and `arg` in the continuation `kc`. If no lock is
102: associated with the continuation, then only arg may be changed.
103: Otherwise, `kcont_setfunc` must be called only when the associated lock
104: is locked.
105:
106: * `bool kcont_stop(kcont_t *kc);`
107:
108: The `kcont_stop function` stops the timer associated the continuation
109: handle kc. The *PENDING* and *EXPIRED* status for the continuation
110: handle is cleared. It is safe to call `kcont_stop` on a continuation
111: handle that is not pending, so long as it is initialized. `kcont_stop`
112: will return a non-zero value if the continuation was *EXPIRED*.
113:
114: * `bool kcont_pending(kcont_t *kc);`
115:
116: The `kcont_pending` function tests the *PENDING* status of the
117: continuation handle `kc`. A *PENDING* continuation is one who's timer
118: has been started and has not expired. Note that it is possible for a
119: continuation's timer to have expired without being invoked if the
120: continuation's lock could not be acquired or there are higher priority
121: threads preventing its invokation. Note that it is only safe to test
122: *PENDING* status when holding the continuation's lock.
123:
124: * `bool kcont_expired(kcont_t *kc);`
125:
126: Tests to see if the continuation's function has been invoked since the
127: last `kcont_schedule`.
128:
129: * `bool kcont_active(kcont_t *kc);`
130:
131: * `bool kcont_invoking(kcont_t *kc);`
132:
133: Tests the *INVOKING* status of the handle `kc`. This flag is set just
134: before a continuation's function is being called. Since the scheduling
135: of the worker threads may induce delays, other pending higher-priority
136: code may run before the continuation function is allowed to run. This
137: may create a race condition if this higher-priority code deallocates
138: storage containing one or more continuation structures whose continuation
139: functions are about to be run. In such cases, one technique to prevent
140: references to deallocated storage would be to test whether any
141: continuation functions are in the *INVOKING* state using
142: `kcont_invoking`, and if so, to mark the data structure and defer storage
143: deallocation until the continuation function is allowed to run. For this
144: handshake protocol to work, the continuation function will have to use
145: the `kcont_ack` function to clear this flag.
146:
147: * `bool kcont_ack(kcont_t *kc);`
148:
149: Clears the *INVOKING* state in the continuation handle `kc`. This is
150: used in situations where it is necessary to protect against the race
151: condition described under `kcont_invoking`.
152:
153: * `kcont_wq_t *kcont_workqueue_acquire(pri_t pri, int flags);`
154:
155: Returns a workqueue that matches the specified criteria. Thus if
156: multiple requesters ask for the same criteria, they are all returned the
157: same workqueue. `pri` specifies the priority at which the kernel thread
158: which empties the workqueue should run.
159:
160: If `flags` is 0 then the standard operation is required. However, the
161: following flag(s) may be bitwise ORed together:
162:
163: * `WQ_PERCPU` specifies that the workqueue should have a separate queue
1.2 plunky 164: for each CPU, thus allowing continuations to be invoked on specific CPUs.
1.1 jmmv 165:
166: * `int kcont_workqueue_release(kcont_wq_t *wq);`
167:
168: Releases an acquired workqueue. On the last release, the workqueue's
169: resources are freed and the workqueue is destroyed.
170: """
171: ]]
172:
173: [[!tag smp_networking]]
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb