Tasklet System

Tasklet

Quasi tutti i moduli che compongono il demone ntkd fanno uso di tasklet per svolgere i loro compiti. Si tratta di thread cooperativi, cioè che permettono allo schedulatore di passare l'esecuzione ad un altro thread soltanto su specifica autorizzazione da parte del thread corrente.

L'autorizzazione a schedulare altre tasklet viene data da parte della tasklet corrente con una delle seguenti modalità:

Inoltre la tasklet corrente può creare altre tasklet, attraverso la funzione spawn . Questo consiste nel dire allo schedulatore che una certa chiamata ad una funzione dovrà essere eseguita in una nuova tasklet. La nuova tasklet non verrà comunque iniziata dallo schedulatore fino a quando la tasklet corrente non lo consentirà attraverso una delle modalità dette in precedenza.

La funzione spawn restituisce un handle per la tasklet creata. Tramite questo handle è possibile verificare se la tasklet è ancora in esecuzione. Si può inoltre richiedere la terminazione della tasklet.

Alla funzione spawn si può indicare se la nuova tasklet dovrà essere joinable . In questo caso tramite il suo handle sarà possibile chiamare il metodo join : la tasklet corrente si blocca in attesa che la tasklet individuata dall'handle termini e poi riceve il valore di ritorno dell'esecuzione della tasklet; si tratta di un void * che di norma è il valore di ritorno della funzione con cui la tasklet ha avuto inizio.

La tasklet corrente può richiedere di terminare se stessa, con un eventuale valore di ritorno, indipendentemente dalla profondità di chiamate nel suo stack che ha raggiunto.

Due tasklet possono comunicare tra loro attraverso un canale . Se due tasklet condividono un canale questo fornisce loro un meccanismo per comunicare tra loro senza bloccarsi.

E' stata realizzata una libreria che contiene alcune interfacce di programmazione verso un generico sistema di tasklet. Si chiama ntkd-tasklet-system.

Questa libreria sarà una dipendenza nel pacchetto software di ogni singolo modulo. Ma tali pacchetti non saranno tenuti ad avere una dipendenza sulla specifica libreria che implementa il sistema di tasklet.

La libreria ntkd-tasklet-system sarà una dipendenza anche nel pacchetto software che raccoglie i vari moduli e produce l'eseguibile del demone ntkd. Il compito di tale pacchetto sarà quello di fornire ai vari moduli una implementazione delle interfacce del sistema di tasklet, quindi avrà una dipendenza anche sulla specifica libreria che usa a tale scopo.

Si cerca così di rendere i vari moduli del demone ntkd indipendenti dalla implementazione delle tasklet. La prima implementazione che useremo nel demone sarà la libreria Tasklet v1.0.1 ma dovrebbe essere possibile usare altre implementazioni.

Interfacce

L'interfaccia INtkdTasklet prevede questi metodi:

L'interfaccia INtkdTaskletSpawnable prevede questi metodi:

L'interfaccia INtkdTaskletHandle prevede questi metodi:

La classe NtkdTaskletCommandResult ha questi membri:

L'interfaccia INtkdServerStreamSocket si usa lato server. Essa prevede questi metodi:

L'interfaccia INtkdConnectedStreamSocket si usa su entrambi gli end point della connessione. Essa prevede questi metodi:

L'interfaccia INtkdServerDatagramSocket prevede questi metodi:

L'interfaccia INtkdClientDatagramSocket prevede questi metodi:

L'interfaccia INtkdChannel prevede questi metodi:

Quando si desidera avviare una tasklet occorre creare appositamente una istanza di una classe che implementa l'interfaccia INtkdTaskletSpawnable. Tale classe ha come membri tutti i dati che andrebbero passati alla funzione che inizia il task. Inoltre ha il metodo func che è proprio quello che costituisce il corpo della tasklet che si vuole avviare. La classe che si istanzia può essere interna ad un'altra classe per fare in modo che abbia accesso ai suoi membri privati.

Poi si valorizzano i membri della istanza di INtkdTaskletSpawnable, come sarebbero passati gli argomenti alla funzione. Quindi si chiama il metodo spawn di INtkdTasklet, al quale si può indicare se si desidera che la nuova tasklet sia joinable.

L'istanza di INtkdTaskletHandle restituita dal metodo spawn potrà essere usata per fare il join della tasklet (se è joinable) oppure in caso di necessità per abortirla.

Quando il metodo spawn restituisce il controllo al chiamante, esso è tenuto a rimuovere immediatamente il suo riferimento alla istanza di INtkdTaskletSpawnable.

Il metodo spawn si occupa di memorizzare un riferimento all'istanza di INtkdTaskletSpawnable per evitare che venga distrutta e di mantenerlo in vita fino alla fine della tasklet che andiamo a creare. Poi il metodo crea la nuova tasklet, che eseguirà un'apposita funzione che chiamiamo real_func , con l'implementazione che si intende adottare, sia essa Tasklet (basata su GNU Pth) o similari. Di norma la funzione real_func ha in C la signature "void *(*)(void *)". Come argomento viene passata l'istanza di INtkdTaskletSpawnable dopo averne fatto il cast a (void *).

Nella nuova tasklet, la funzione real_func riceve il dato come (void *) e ne fa il cast a (INtkdTaskletSpawnable *). Poi richiama il suo metodo func e memorizza il suo valore di ritorno. Infine rimuove il riferimento all'istanza di INtkdTaskletSpawnable e poi termina restituendo il valore di ritorno di func .

Inizializzazione

I moduli del demone ntkd che fanno uso delle tasklet vengono "inizializzati" con alcune chiamate, fra cui il metodo init_tasklet_system . In esso il modulo principale fornisce le implementazioni delle interfacce usate per le comunicazioni allo schedulatore.

Praticamente deve fornire una istanza di INtkdTasklet.