L4Re/departure

libexec/lib/src/process_monitor.cc

618:7123a7307a82
8 months ago Paul Boddie Introduced some debugging output control.
     1 /*     2  * A process monitor abstraction.     3  *     4  * Copyright (C) 2022, 2023, 2024 Paul Boddie <paul@boddie.org.uk>     5  *     6  * This program is free software; you can redistribute it and/or     7  * modify it under the terms of the GNU General Public License as     8  * published by the Free Software Foundation; either version 2 of     9  * the License, or (at your option) any later version.    10  *    11  * This program is distributed in the hope that it will be useful,    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    14  * GNU General Public License for more details.    15  *    16  * You should have received a copy of the GNU General Public License    17  * along with this program; if not, write to the Free Software    18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,    19  * Boston, MA  02110-1301, USA    20  */    21     22 #include <l4/sys/thread.h>    23     24 #include <ipc/cap_alloc.h>    25 #include <ipc/map.h>    26 #include <systypes/base.h>    27     28 #include <stdio.h>    29     30 #include "process_monitor.h"    31 #include "parent_notification_object_server.h"    32     33     34     35 /* A process monitor receiving signals from a task. */    36     37 ProcessMonitor::ProcessMonitor(bool debug)    38 : NotificationSupport(), _debug(debug)    39 {    40 }    41     42 ipc_server_default_config_type ProcessMonitor::config()    43 {    44   return config_ParentNotificationObject;    45 }    46     47     48     49 /* Close the process monitor. */    50     51 void ProcessMonitor::close()    52 {    53   if (_debug)    54     printf("Process monitor closing...\n");    55 }    56     57     58     59 /* Capability management. */    60     61 void ProcessMonitor::set_pager(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap)    62 {    63   _pager = cap;    64   _mapped_pager = mapped_cap;    65 }    66     67 void ProcessMonitor::set_parent(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap)    68 {    69   _parent = cap;    70   _mapped_parent = mapped_cap;    71 }    72     73 void ProcessMonitor::set_task(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap)    74 {    75   _task = cap;    76   _mapped_task = mapped_cap;    77 }    78     79 void ProcessMonitor::set_thread(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap)    80 {    81   _thread = cap;    82   _mapped_thread = mapped_cap;    83 }    84     85     86     87 /* Lifecycle management. */    88     89 void ProcessMonitor::pager_ended()    90 {    91   /* Release the program thread and its reference to this object, leaving only    92      the program initiator with a reference. When the initiator releases its    93      reference, this object will be closed. */    94     95   if (l4_is_valid_cap(_thread))    96   {    97     ipc_unmap_capability(_task, _mapped_thread);    98     ipc_cap_free_um(_thread);    99     _thread = L4_INVALID_CAP;   100    101     ipc_unmap_capability(_task, _mapped_parent);   102   }   103    104   /* Release the program task. This will release any capabilities that might be   105      blocking the initiator, such as those involving pipes or streams. */   106    107   if (l4_is_valid_cap(_task))   108   {   109     ipc_unmap_capability(_task, _mapped_task);   110     ipc_cap_free_um(_task);   111     _task = L4_INVALID_CAP;   112   }   113 }   114    115    116    117 /* Receive signals from a task. */   118    119 long ProcessMonitor::signal(unsigned long sig, unsigned long val)   120 {   121   notify_all(NOTIFY_TASK_SIGNAL, (notify_values_t) {sig, val});   122    123   /* Handle the termination event. */   124    125   if (sig == 0)   126   {   127     if (_debug)   128       printf("Signal from task.\n");   129    130     /* Cancel any IPC to avoid spurious pager warnings. */   131    132     l4_thread_ex_regs(_pager, ~0UL, ~0UL, L4_THREAD_EX_REGS_CANCEL);   133    134     /* Once the program exits, the IPC gate connecting the program with its   135        internal pager can be released. This will cause the internal pager to   136        finish, which is then handled by the external pager. */   137    138     if (l4_is_valid_cap(_pager))   139     {   140       ipc_cap_free_um(_pager);   141       _pager = L4_INVALID_CAP;   142     }   143    144     /* The thread is not released here since the initiator of the process   145        needs to be able to receive a reference to this object, but if the   146        process terminates and the thread is released, this object may be   147        released before the initiator obtains a reference to it. */   148   }   149    150   return L4_EOK;   151 }   152    153    154    155 /* Subscribe to notifications. */   156    157 long ProcessMonitor::subscribe(l4_cap_idx_t notifier, notify_flags_t flags)   158 {   159   unsubscribe();   160    161   _notifier = notifier;   162   return NotificationSupport::subscribe(_notifier, flags);   163 }   164    165 /* Unsubscribe from notifications. */   166    167 long ProcessMonitor::unsubscribe()   168 {   169   if (l4_is_valid_cap(_notifier))   170   {   171     long err = NotificationSupport::unsubscribe(_notifier);   172     _notifier = L4_INVALID_CAP;   173     return err;   174   }   175   else   176     return L4_EOK;   177 }   178    179 /* vim: tabstop=2 expandtab shiftwidth=2   180 */