source: mainline/uspace/lib/system/src/system.c@ a72f3b8

Last change on this file since a72f3b8 was a72f3b8, checked in by Jiri Svoboda <jiri@…>, 8 months ago

System protocol library, incl. unit tests

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2024 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libsystem
30 * @{
31 */
32/** @file System control service interface
33 */
34
35#include <async.h>
36#include <assert.h>
37#include <system.h>
38#include <errno.h>
39#include <fibril_synch.h>
40#include <ipc/system.h>
41#include <loc.h>
42#include <stdlib.h>
43#include "../private/system.h"
44
45static errno_t system_callback_create(system_t *);
46static void system_cb_conn(ipc_call_t *, void *);
47
48/** Open system control service.
49 *
50 * @param svcname Service name
51 * @param cb Pointer to callback structure
52 * @param arg Argument passed to callback functions
53 * @param rsystem Place to store pointer to system control service object.
54 *
55 * @return EOK on success or an error code
56 */
57errno_t system_open(const char *svcname, system_cb_t *cb, void *arg,
58 system_t **rsystem)
59{
60 service_id_t system_svc;
61 async_sess_t *sess;
62 system_t *system;
63 errno_t rc;
64
65 system = calloc(1, sizeof(system_t));
66 if (system == NULL)
67 return ENOMEM;
68
69 fibril_mutex_initialize(&system->lock);
70 fibril_condvar_initialize(&system->cv);
71
72 rc = loc_service_get_id(svcname, &system_svc, IPC_FLAG_BLOCKING);
73 if (rc != EOK)
74 goto error;
75
76 sess = loc_service_connect(system_svc, INTERFACE_SYSTEM,
77 IPC_FLAG_BLOCKING);
78 if (sess == NULL)
79 goto error;
80
81 system->sess = sess;
82 system->cb = cb;
83 system->cb_arg = arg;
84
85 rc = system_callback_create(system);
86 if (rc != EOK) {
87 async_hangup(sess);
88 goto error;
89 }
90
91 *rsystem = system;
92 return EOK;
93error:
94 free(system);
95 return rc;
96}
97
98/** Close system control service.
99 *
100 * @param system System control service
101 */
102void system_close(system_t *system)
103{
104 fibril_mutex_lock(&system->lock);
105 async_hangup(system->sess);
106 system->sess = NULL;
107
108 /* Wait for callback handler to terminate */
109
110 while (!system->cb_done)
111 fibril_condvar_wait(&system->cv, &system->lock);
112 fibril_mutex_unlock(&system->lock);
113
114 free(system);
115}
116
117/** Create callback connection from system control service.
118 *
119 * @param system System control service
120 * @return EOK on success or an error code
121 */
122static errno_t system_callback_create(system_t *system)
123{
124 async_exch_t *exch = async_exchange_begin(system->sess);
125
126 aid_t req = async_send_0(exch, SYSTEM_CALLBACK_CREATE, NULL);
127
128 port_id_t port;
129 errno_t rc = async_create_callback_port(exch, INTERFACE_SYSTEM_CB, 0, 0,
130 system_cb_conn, system, &port);
131
132 async_exchange_end(exch);
133
134 if (rc != EOK)
135 return rc;
136
137 errno_t retval;
138 async_wait_for(req, &retval);
139
140 return retval;
141}
142
143/** Shut the system down.
144 *
145 * This function is asynchronous. It returns immediately with success
146 * if the system started shutting down. Once shutdown is completed,
147 * the @c shutdown_complete callback is executed. If the shutdown fails,
148 * the @c shutdown_fail callback is executed.
149 *
150 * @param system System control service
151 * @return EOK on succes or an error code
152 */
153errno_t system_shutdown(system_t *system)
154{
155 async_exch_t *exch = async_exchange_begin(system->sess);
156 errno_t rc = async_req_0_0(exch, SYSTEM_SHUTDOWN);
157 async_exchange_end(exch);
158
159 return rc;
160}
161
162/** System shutdown completed.
163 *
164 * @param system System control service
165 * @param icall Call data
166 */
167static void system_shutdown_complete(system_t *system, ipc_call_t *icall)
168{
169 if (system->cb != NULL && system->cb->shutdown_complete != NULL)
170 system->cb->shutdown_complete(system->cb_arg);
171
172 async_answer_0(icall, EOK);
173}
174
175/** System shutdown failed.
176 *
177 * @param system System control service
178 * @param icall Call data
179 */
180static void system_shutdown_failed(system_t *system, ipc_call_t *icall)
181{
182 if (system->cb != NULL && system->cb->shutdown_complete != NULL)
183 system->cb->shutdown_failed(system->cb_arg);
184
185 async_answer_0(icall, EOK);
186}
187
188/** Callback connection handler.
189 *
190 * @param icall Connect call data
191 * @param arg Argument, system_t *
192 */
193static void system_cb_conn(ipc_call_t *icall, void *arg)
194{
195 system_t *system = (system_t *) arg;
196
197 while (true) {
198 ipc_call_t call;
199 async_get_call(&call);
200
201 if (!ipc_get_imethod(&call)) {
202 /* Hangup */
203 async_answer_0(&call, EOK);
204 goto out;
205 }
206
207 switch (ipc_get_imethod(&call)) {
208 case SYSTEM_SHUTDOWN_COMPLETE:
209 system_shutdown_complete(system, &call);
210 break;
211 case SYSTEM_SHUTDOWN_FAILED:
212 system_shutdown_failed(system, &call);
213 break;
214 default:
215 async_answer_0(&call, ENOTSUP);
216 break;
217 }
218 }
219
220out:
221 fibril_mutex_lock(&system->lock);
222 system->cb_done = true;
223 fibril_mutex_unlock(&system->lock);
224 fibril_condvar_broadcast(&system->cv);
225}
226
227/** @}
228 */
Note: See TracBrowser for help on using the repository browser.