# HG changeset patch # User Paul Boddie # Date 1702081639 -3600 # Node ID 66ab00dc7dd03337794113d8c8a26da93c6c316f # Parent b2aa14224c26e041fcaa80b2b52f2630a8d47bcb Consolidated some of the notification functionality. diff -r b2aa14224c26 -r 66ab00dc7dd0 docs/wiki/Client_Library --- a/docs/wiki/Client_Library Sat Dec 09 01:26:55 2023 +0100 +++ b/docs/wiki/Client_Library Sat Dec 09 01:27:19 2023 +0100 @@ -228,39 +228,39 @@ a given resource via a notifier object: {{{ -long client_subscribe(file_t *file, notify_flags_t flags, file_notifier_t *notifier); +long client_subscribe(file_t *file, notify_flags_t flags, notifier_t *notifier); }}} A notifier object can be common throughout all threads in a task, being obtained using the following function: {{{ -file_notifier_t *client_notifier_task(); +notifier_t *client_notifier_task(); }}} Alternatively, a local notifier can be created for use within a thread: {{{ -file_notifier_t *client_notifier_local(); +notifier_t *client_notifier_local(); }}} Local notifiers must be closed when they are no longer needed: {{{ -void client_notifier_close(file_notifier_t *notifier); +void client_notifier_close(notifier_t *notifier); }}} When notifications are no longer needed, an unsubscribe operation can be invoked: {{{ -long client_unsubscribe(file_t *file, file_notifier_t *notifier); +long client_unsubscribe(file_t *file, notifier_t *notifier); }}} ==== Example ==== {{{ -file_notifier_t *notifier = client_notifier_local(); +notifier_t *notifier = client_notifier_local(); file_t *directory = client_open(filename, O_DIRECTORY); if (client_opened(directory)) diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/include/fsclient/client.h --- a/libfsclient/include/fsclient/client.h Sat Dec 09 01:26:55 2023 +0100 +++ b/libfsclient/include/fsclient/client.h Sat Dec 09 01:27:19 2023 +0100 @@ -100,14 +100,15 @@ /* More advanced notification operations. */ -void client_notifier_close(file_notifier_t *notifier); -file_notifier_t *client_notifier_local(void); -file_notifier_t *client_notifier_task(void); +void client_notifier_close(notifier_t *notifier); +notifier_t *client_notifier_local(void); +notifier_t *client_notifier_task(void); -long client_subscribe(file_t *file, notify_flags_t flags, file_notifier_t *notifier); -long client_unsubscribe(file_t *file, file_notifier_t *notifier); -long client_wait_file(file_t *file, file_notifier_t *notifier); -long client_wait_files(file_t **file, file_notifier_t *notifier); +long client_subscribe(file_t *file, notify_flags_t flags, notifier_t *notifier); +long client_unsubscribe(file_t *file, notifier_t *notifier); + +long client_wait_file(file_t *file, notifier_t *notifier); +long client_wait_files(file_t **file, notifier_t *notifier); EXTERN_C_END diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/include/fsclient/file.h --- a/libfsclient/include/fsclient/file.h Sat Dec 09 01:26:55 2023 +0100 +++ b/libfsclient/include/fsclient/file.h Sat Dec 09 01:27:19 2023 +0100 @@ -29,13 +29,7 @@ #include #include - - -/* C compatibility types (defined in the implementation). */ - -struct file_notifier; - -typedef struct file_notifier file_notifier_t; +#include @@ -49,6 +43,10 @@ l4_cap_idx_t ref; + /* Notification structure. */ + + notifiable_t notifiable; + /* Mapped memory accessing a file region. */ char *memory; @@ -71,10 +69,6 @@ notify_flags_t can_block; - /* Notification structure. */ - - notifiable_t notifiable; - /* Flags indicated when opening the file. */ flags_t flags; @@ -151,14 +145,8 @@ notifiable_t *file_notifiable(file_t *file); notify_flags_t file_notifications(file_t *file); -void file_notify_close(file_notifier_t *notifier); -file_notifier_t *file_notify_local(void); -file_notifier_t *file_notify_task(void); - -long file_notify_subscribe(file_t *file, notify_flags_t flags, file_notifier_t *notifier); -long file_notify_unsubscribe(file_t *file, file_notifier_t *notifier); -long file_notify_wait_file(file_t *file, file_notifier_t *notifier); -long file_notify_wait_files(file_t **file, file_notifier_t *notifier); +long file_notify_wait_file(file_t *file, notifier_t *notifier); +long file_notify_wait_files(file_t **file, notifier_t *notifier); diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/include/fsclient/notify.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/include/fsclient/notify.h Sat Dec 09 01:27:19 2023 +0100 @@ -0,0 +1,55 @@ +/* + * Notification-related functions and types. + * + * Copyright (C) 2023 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* C compatibility types (defined in the implementation). */ + +struct notifier; + +typedef struct notifier notifier_t; + + + +EXTERN_C_BEGIN + +notifiable_t *notify_notifiable(notifiable_base_t *notifiable); +notify_flags_t notify_notifications(notifiable_base_t *notifiable); +notify_values_t notify_notification_values(notifiable_base_t *notifiable); + +void notify_close(notifier_t *notifier); + +notifier_t *notify_get_local(void); +notifier_t *notify_get_task(void); + +long notify_subscribe(notifiable_t *notifiable, notify_flags_t flags, notifier_t *notifier); +long notify_unsubscribe(notifiable_t *notifiable, notifier_t *notifier); + +long notify_wait(notifiable_t *notifiable, notifier_t *notifier); +long notify_wait_many(notifiable_t **notifiable, notifier_t *notifier); + +EXTERN_C_END + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/include/fsclient/process.h --- a/libfsclient/include/fsclient/process.h Sat Dec 09 01:26:55 2023 +0100 +++ b/libfsclient/include/fsclient/process.h Sat Dec 09 01:27:19 2023 +0100 @@ -28,14 +28,6 @@ -/* C compatibility types (defined in the implementation). */ - -struct process_notifier; - -typedef struct process_notifier process_notifier_t; - - - EXTERN_C_BEGIN /* File access abstraction compatible with notifiable_base_t. */ @@ -67,13 +59,9 @@ notifiable_t *process_notifiable(process_t *process); notify_flags_t process_notifications(process_t *process); notify_values_t process_notification_values(process_t *process); -void process_notify_close(process_notifier_t *notifier); -process_notifier_t *process_notify_local(); -process_notifier_t *process_notify_task(); -long process_notify_subscribe(process_t *process, notify_flags_t flags, process_notifier_t *notifier); -long process_notify_unsubscribe(process_t *process, process_notifier_t *notifier); -long process_notify_wait_process(process_t *process, process_notifier_t *notifier); -long process_notify_wait_processes(process_t **process, process_notifier_t *notifier); + +long process_notify_wait_process(process_t *process, notifier_t *notifier); +long process_notify_wait_processes(process_t **process, notifier_t *notifier); EXTERN_C_END diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/lib/src/Makefile --- a/libfsclient/lib/src/Makefile Sat Dec 09 01:26:55 2023 +0100 +++ b/libfsclient/lib/src/Makefile Sat Dec 09 01:27:19 2023 +0100 @@ -23,7 +23,7 @@ CLIENT_INTERFACES_SRC_CC = $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC)) -PLAIN_SRC_CC = client.cc file.cc process.cc +PLAIN_SRC_CC = client.cc file.cc notify.cc process.cc # Normal definitions. diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/lib/src/client.cc --- a/libfsclient/lib/src/client.cc Sat Dec 09 01:26:55 2023 +0100 +++ b/libfsclient/lib/src/client.cc Sat Dec 09 01:27:19 2023 +0100 @@ -557,23 +557,23 @@ /* Close a notifier object. */ -void client_notifier_close(file_notifier_t *notifier) +void client_notifier_close(notifier_t *notifier) { - file_notify_close(notifier); + notify_close(notifier); } /* Obtain a local notifier object. */ -file_notifier_t *client_notifier_local() +notifier_t *client_notifier_local() { - return file_notify_local(); + return notify_get_local(); } /* Obtain a task-wide notifier object. */ -file_notifier_t *client_notifier_task() +notifier_t *client_notifier_task() { - return file_notify_task(); + return notify_get_task(); } @@ -766,7 +766,7 @@ /* Since blocking access is used with specific file notifications, the per-task notifier is used. */ - file_notifier_t *notifier = client_notifier_task(); + notifier_t *notifier = client_notifier_task(); if (flags) err = client_subscribe(file, flags, notifier); @@ -784,12 +784,12 @@ /* Subscribe from events concerning a file. */ -long client_subscribe(file_t *file, notify_flags_t flags, file_notifier_t *notifier) +long client_subscribe(file_t *file, notify_flags_t flags, notifier_t *notifier) { if (!client_opened(file)) return -L4_EINVAL; - return file_notify_subscribe(file, flags, notifier); + return notify_subscribe(file_notifiable(file), flags, notifier); } @@ -808,19 +808,19 @@ /* Unsubscribe from events concerning a file. */ -long client_unsubscribe(file_t *file, file_notifier_t *notifier) +long client_unsubscribe(file_t *file, notifier_t *notifier) { if (!client_opened(file)) return -L4_EINVAL; - return file_notify_unsubscribe(file, notifier); + return notify_unsubscribe(file_notifiable(file), notifier); } /* Wait for events involving a specific file. */ -long client_wait_file(file_t *file, file_notifier_t *notifier) +long client_wait_file(file_t *file, notifier_t *notifier) { if (!client_opened(file)) return -L4_EINVAL; @@ -831,7 +831,7 @@ /* Wait for events concerning files, referencing a file object if an event is delivered. */ -long client_wait_files(file_t **file, file_notifier_t *notifier) +long client_wait_files(file_t **file, notifier_t *notifier) { return file_notify_wait_files(file, notifier); } diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/lib/src/file.cc --- a/libfsclient/lib/src/file.cc Sat Dec 09 01:26:55 2023 +0100 +++ b/libfsclient/lib/src/file.cc Sat Dec 09 01:27:19 2023 +0100 @@ -611,96 +611,47 @@ -/* Opaque notifier type for file_notifier_t. */ - -struct file_notifier -{ - ObjectNotifier *obj; -}; - /* Conversion to the generic notification types. */ notifiable_t *file_notifiable(file_t *file) { - return &file->notifiable; + return notify_notifiable((notifiable_base_t *) file); } /* Return the notification flags for a file. */ notify_flags_t file_notifications(file_t *file) { - return file->notifiable.notifications; -} - -/* Close a notifier object. */ - -void file_notify_close(file_notifier_t *notifier) -{ - delete notifier->obj; - delete notifier; -} - -/* Obtain a local notifier object. */ - -file_notifier_t *file_notify_local() -{ - file_notifier_t *notifier = new file_notifier_t; - - notifier->obj = notifier_get_local_notifier(); - return notifier; -} - -/* Obtain the task-wide notifier object. */ - -file_notifier_t *file_notify_task() -{ - file_notifier_t *notifier = new file_notifier_t; - - notifier->obj = notifier_get_task_notifier(); - return notifier; -} - -/* Subscribe to notification events on a file. */ - -long file_notify_subscribe(file_t *file, notify_flags_t flags, file_notifier_t *notifier) -{ - return notifier->obj->subscribe(file_notifiable(file), flags); -} - -/* Unsubscribe from notification events on a file. */ - -long file_notify_unsubscribe(file_t *file, file_notifier_t *notifier) -{ - return notifier->obj->unsubscribe(file_notifiable(file)); + return notify_notifications((notifiable_base_t *) file); } /* Wait for a notification event on a file. */ -long file_notify_wait_file(file_t *file, file_notifier_t *notifier) +long file_notify_wait_file(file_t *file, notifier_t *notifier) { - long err = notifier->obj->wait_object(file_notifiable(file)); + long err = notify_wait(file_notifiable(file), notifier); /* Unsubscribe if a closure notification has been received. */ - if (!err && (file->notifiable.notifications & NOTIFY_PEER_CLOSED)) - file_notify_unsubscribe(file, notifier); + if (!err && (file_notifications(file) & NOTIFY_PEER_CLOSED)) + notify_unsubscribe(file_notifiable(file), notifier); return err; } /* Wait for notification events on files. */ -long file_notify_wait_files(file_t **file, file_notifier_t *notifier) +long file_notify_wait_files(file_t **file, notifier_t *notifier) { notifiable_t *notifiable; - long err = notifier->obj->wait(¬ifiable); + long err = notify_wait_many(¬ifiable, notifier); *file = (file_t *) notifiable->base; /* Unsubscribe if a closure notification has been received. */ - if (!err && ((*file)->notifiable.notifications & NOTIFY_PEER_CLOSED)) - file_notify_unsubscribe(*file, notifier); + if (!err && (notifiable->notifications & NOTIFY_PEER_CLOSED)) + notify_unsubscribe(notifiable, notifier); return err; } diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/lib/src/notify.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/lib/src/notify.cc Sat Dec 09 01:27:19 2023 +0100 @@ -0,0 +1,112 @@ +/* + * Notification-related functions. + * + * Copyright (C) 2023 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include "notify.h" + + + +/* Opaque notifier type for notifier_t. */ + +struct notifier +{ + ObjectNotifier *obj; +}; + +/* Return the notifiable details from a compatible object. */ + +notifiable_t *notify_notifiable(notifiable_base_t *notifiable) +{ + return ¬ifiable->notifiable; +} + +/* Return the notification flags for an object. */ + +notify_flags_t notify_notifications(notifiable_base_t *notifiable) +{ + return notifiable->notifiable.notifications; +} + +/* Return the notification values for an object. */ + +notify_values_t notify_notification_values(notifiable_base_t *notifiable) +{ + return notifiable->notifiable.values; +} + +/* Close a notifier object. */ + +void notify_close(notifier_t *notifier) +{ + delete notifier->obj; + delete notifier; +} + +/* Obtain a local notifier object. */ + +notifier_t *notify_get_local() +{ + notifier_t *notifier = new notifier_t; + + notifier->obj = notifier_get_local_notifier(); + return notifier; +} + +/* Obtain the task-wide notifier object. */ + +notifier_t *notify_get_task() +{ + notifier_t *notifier = new notifier_t; + + notifier->obj = notifier_get_task_notifier(); + return notifier; +} + +/* Subscribe to notification events. */ + +long notify_subscribe(notifiable_t *notifiable, notify_flags_t flags, notifier_t *notifier) +{ + return notifier->obj->subscribe(notifiable, flags); +} + +/* Unsubscribe from notification events. */ + +long notify_unsubscribe(notifiable_t *notifiable, notifier_t *notifier) +{ + return notifier->obj->unsubscribe(notifiable); +} + +/* Wait for a notification event on a single object. */ + +long notify_wait(notifiable_t *notifiable, notifier_t *notifier) +{ + return notifier->obj->wait_object(notifiable); +} + +/* Wait for notification events on multiple objects. */ + +long notify_wait_many(notifiable_t **notifiable, notifier_t *notifier) +{ + return notifier->obj->wait(notifiable); +} + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r b2aa14224c26 -r 66ab00dc7dd0 libfsclient/lib/src/process.cc --- a/libfsclient/lib/src/process.cc Sat Dec 09 01:26:55 2023 +0100 +++ b/libfsclient/lib/src/process.cc Sat Dec 09 01:27:19 2023 +0100 @@ -36,11 +36,11 @@ /* Utility functions. */ -static bool _process_terminated(process_t *process) +static bool _process_terminated(notifiable_t *notifiable) { - return ((process->notifiable.notifications & NOTIFY_TASK_SIGNAL) && - (process->notifiable.values.sig == 0)) || - (process->notifiable.notifications & NOTIFY_TASK_ERROR); + return ((notifiable->notifications & NOTIFY_TASK_SIGNAL) && + (notifiable->values.sig == 0)) || + (notifiable->notifications & NOTIFY_TASK_ERROR); } @@ -146,106 +146,54 @@ -/* NOTE: Much of the code below could be unified with the file-related - notification code. */ - -/* Opaque notifier type for process_notifier_t. */ - -struct process_notifier -{ - ObjectNotifier *obj; -}; - /* Conversion to the generic notification types. */ notifiable_t *process_notifiable(process_t *process) { - return &process->notifiable; + return notify_notifiable((notifiable_base_t *) process); } /* Return the notification flags for a process. */ notify_flags_t process_notifications(process_t *process) { - return process->notifiable.notifications; + return notify_notifications((notifiable_base_t *) process); } /* Return the notification values for a process. */ notify_values_t process_notification_values(process_t *process) { - return process->notifiable.values; -} - -/* Close a notifier object. */ - -void process_notify_close(process_notifier_t *notifier) -{ - delete notifier->obj; - delete notifier; -} - -/* Obtain a local notifier object. */ - -process_notifier_t *process_notify_local() -{ - process_notifier_t *notifier = new process_notifier_t; - - notifier->obj = notifier_get_local_notifier(); - return notifier; -} - -/* Obtain the task-wide notifier object. */ - -process_notifier_t *process_notify_task() -{ - process_notifier_t *notifier = new process_notifier_t; - - notifier->obj = notifier_get_task_notifier(); - return notifier; -} - -/* Subscribe to notification events on a process. */ - -long process_notify_subscribe(process_t *process, notify_flags_t flags, process_notifier_t *notifier) -{ - return notifier->obj->subscribe(process_notifiable(process), flags); -} - -/* Unsubscribe from notification events on a process. */ - -long process_notify_unsubscribe(process_t *process, process_notifier_t *notifier) -{ - return notifier->obj->unsubscribe(process_notifiable(process)); + return notify_notification_values((notifiable_base_t *) process); } /* Wait for a notification event on a process. */ -long process_notify_wait_process(process_t *process, process_notifier_t *notifier) +long process_notify_wait_process(process_t *process, notifier_t *notifier) { - long err = notifier->obj->wait_object(process_notifiable(process)); + long err = notify_wait(process_notifiable(process), notifier); /* Unsubscribe if a termination notification has been received. */ - if (!err && _process_terminated(process)) - process_notify_unsubscribe(process, notifier); + if (!err && _process_terminated(process_notifiable(process))) + notify_unsubscribe(process_notifiable(process), notifier); return err; } /* Wait for notification events on processes. */ -long process_notify_wait_processes(process_t **process, process_notifier_t *notifier) +long process_notify_wait_processes(process_t **process, notifier_t *notifier) { notifiable_t *notifiable; - long err = notifier->obj->wait(¬ifiable); + long err = notify_wait_many(¬ifiable, notifier); *process = (process_t *) notifiable->base; /* Unsubscribe if a termination notification has been received. */ - if (!err && _process_terminated(*process)) - process_notify_unsubscribe(*process, notifier); + if (!err && _process_terminated(notifiable)) + notify_unsubscribe(notifiable, notifier); return err; } diff -r b2aa14224c26 -r 66ab00dc7dd0 libsystypes/include/systypes/base.h --- a/libsystypes/include/systypes/base.h Sat Dec 09 01:26:55 2023 +0100 +++ b/libsystypes/include/systypes/base.h Sat Dec 09 01:27:19 2023 +0100 @@ -73,13 +73,13 @@ /* Notifiable object types. */ -typedef struct -{ - l4_cap_idx_t ref; +/* Forward reference. */ + +typedef struct notifiable_base notifiable_base_t; -} notifiable_base_t; +/* Structure maintaining notification state for a specific object. */ -typedef struct +typedef struct notifiable { notifiable_base_t *base; /* access to the specific object */ notify_flags_t notifications; /* essential notifications */ @@ -90,6 +90,16 @@ } notifiable_t; +/* A base structure extended by notifiable object structures like files and + processes. */ + +typedef struct notifiable_base +{ + l4_cap_idx_t ref; + notifiable_t notifiable; + +} notifiable_base_t; + /* Filesystem object properties. */ typedef unsigned long object_flags_t; diff -r b2aa14224c26 -r 66ab00dc7dd0 tests/dstest_exec.cc --- a/tests/dstest_exec.cc Sat Dec 09 01:26:55 2023 +0100 +++ b/tests/dstest_exec.cc Sat Dec 09 01:27:19 2023 +0100 @@ -32,7 +32,7 @@ { /* Obtain the common notifier. */ - process_notifier_t *notifier = process_notify_task(); + notifier_t *notifier = notify_get_task(); /* Create a new process structure. */ @@ -54,7 +54,7 @@ /* Subscribe to the process for notifications. */ - err = process_notify_subscribe(&process, NOTIFY_TASK_ALL, notifier); + err = notify_subscribe(process_notifiable(&process), NOTIFY_TASK_ALL, notifier); if (err) { @@ -96,7 +96,7 @@ /* Obtain the common notifier. */ - process_notifier_t *notifier = process_notify_task(); + notifier_t *notifier = notify_get_task(); /* Start a process for a non-existent program. */ @@ -123,7 +123,7 @@ if (err) return 1; - process_notify_close(notifier); + notify_close(notifier); printf("End of test.\n"); return 0; diff -r b2aa14224c26 -r 66ab00dc7dd0 tests/dstest_exec_many.cc --- a/tests/dstest_exec_many.cc Sat Dec 09 01:26:55 2023 +0100 +++ b/tests/dstest_exec_many.cc Sat Dec 09 01:27:19 2023 +0100 @@ -43,7 +43,7 @@ /* Obtain the common notifier. */ - process_notifier_t *notifier = process_notify_task(); + notifier_t *notifier = notify_get_task(); /* Create a new process structure. */ @@ -69,7 +69,7 @@ /* Subscribe to the process for notifications. */ - err = process_notify_subscribe(&process, NOTIFY_TASK_ALL, notifier); + err = notify_subscribe(process_notifiable(&process), NOTIFY_TASK_ALL, notifier); if (err) { @@ -95,7 +95,7 @@ process_close(&process); } - process_notify_close(notifier); + notify_close(notifier); printf("End of test.\n"); return 0; diff -r b2aa14224c26 -r 66ab00dc7dd0 tests/dstest_pipe_client.cc --- a/tests/dstest_pipe_client.cc Sat Dec 09 01:26:55 2023 +0100 +++ b/tests/dstest_pipe_client.cc Sat Dec 09 01:27:19 2023 +0100 @@ -89,7 +89,7 @@ /* Use a local notifier to wait for pipe events. */ - file_notifier_t *notifier = client_notifier_local(); + notifier_t *notifier = client_notifier_local(); /* Register the readers for notification. */