File: USERUI_API

package info (click to toggle)
tuxonice-userui 1.1%2Bdfsg1.gc3bdd83-4
  • links: PTS, VCS
  • area: contrib
  • in suites: bookworm, bullseye, buster, stretch
  • size: 664 kB
  • ctags: 2,034
  • sloc: ansic: 5,786; makefile: 91; sh: 63; python: 46
file content (172 lines) | stat: -rw-r--r-- 6,967 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
This file describes the API between userui_core and a userui plugin (eg,
userui_text). It does not cover the kernel API, which is detailed in the file
KERNEL_API. You want to read this file if you plan to write your own user
interface.




Function API
------------

Each userui module should define a struct userui_ops describing its operations,
and also define a pointer to it called "userui_ops". See userui_skeleton.c for
an example.  The userui_ops struct defined for your module must contain the
following elements :

        char *name;
        void (*prepare) ();
        void (*cleanup) ();
        void (*message) (unsigned long type, unsigned long level, int normally_logged, char *text);
        void (*update_progress) (unsigned long value, unsigned long maximum, char *text);
        void (*log_level_change) ();
        void (*redraw) ();
        void (*keypress) (int key);

And some optional ones:

        unsigned long (*memory_required) ();

        char *optstring;
        struct option *longopts;
        int (*option_handler) (char c);
        char *(*cmdline_options) ();

Each element in turn is described below:

char *name;
  This is a short string identifying your module.

void prepare()
  This function is the first to be called in your module. It is run pretty soon
  after the suspend cycle has started. This is where you do all your setup -
  this entails opening and reading all the files you will need, allocating all
  the memory you will need and anything else to avoid touching the filesystem
  once suspending has started. Hibernating will not proceed until this function
  exits. If you really need to abort the suspend process because something
  failed (not really recommended), you can send a USERUI_MSG_ABORT. This is
  described in Communicating with TuxOnIce.

void cleanup()
  This is called after the suspend has completed (either through resuming or
  aborting). It is expected to clean up things like the console and undo any
  effects of prepare() that would otherwise persist.

void message(type, level, normally_logged, text)
  This function is called by TuxOnIce when it wishes to update the message
  on the screen.  FIXME ... fill in details of parameters!

void update_progress(value, maximum, text)
  This function is called by TuxOnIce to update progress of suspending or
  resuming. The text parameter specifies the text to display in the middle of the
  progress bar.

void log_level_change()
  Notifies the UI module that the kernel loglevel (given in console_loglevel)
  has changed - it may wish to update the display to give more or less
  verbosity as required.

void redraw()
  Upon resuming, immediately after copying the original kernel back, video memory
  is normally filled with old boot messages that need to be cleared. This function
  is called to clear and redraw the screen from scratch.

void keypress(int key)
  If the user presses a key whilst suspending, this function is called with the
  appropriate keycode.



The following functions are optional:

unsigned long memory_required()
  If the process will require a given amount of memory for suspending, that has
  not yet been allocated, it can specify an amount here (in bytes).

char *optstring
  If the userui module wishes to accept extra command-line options, it can
  specify a string of characters here (getopt-style). Module authors should
  verify that it does not clash with existing options in handle_params() in
  userui_core.c.

struct option *longopts
  If the userui module wishes to accept long-style command-line options, it can
  specify a pointer to an empty-terminated array of struct option's.

int option_handler(char c)
  If not NULL, this function is called when command-line options are found that
  the userui_core could not handle. If the module handles the given option,
  then it should return 1. If not, it should return 0.

char *cmdline_options()
  This function should returns a string containing the usage text for the extra
  options provided by this module.

Communicating with TuxOnIce
---------------------------

Most of the messages are handled by userui_core, but there may arise occasions
where you wish to manipulate TuxOnIce directly. This can be achieved by
using the send_message function:
        int send_message(int type, void* buf, int len);

This function returns 1 on success (the message was successfully sent to the
kernel) or 0 on failure. Some messages of interest are:

 type = USERUI_MSG_ABORT (no parameters)
   Aborts the current suspend cycle (eg because the user pressed Escape).

 type = USERUI_MSG_SET_STATE, buf = &suspend_action, len = sizeof(int)
   Sets the suspend_action variable to the given value. This allows you to
   change the following flags: SUSPEND_REBOOT, SUSPEND_PAUSE, SUSPEND_SLOW,
   SUSPEND_LOGALL, SUSPEND_SINGLESTEP, SUSPEND_PAUSE_NEAR_PAGESET_END.

 type = USERUI_MSG_GET_STATE (no parameters)
   This will tell the kernel to reply with the current suspend_action value.
   You should call this after a call to USERUI_MSG_SET_STATE to ensure the
   kernel and userspace are in sync.

 type = USERUI_MSG_SET_LOGLEVEL, buf = &new_loglevel, len = sizeof(int)
   Sets the console loglevel to the given value.

 type = USERUI_MSG_GET_LOGLEVEL, buf = &new_loglevel, len = sizeof(int)
   Gets the current console loglevel, and calls the log_level_change function
   to report it.




Restrictions on your userui module
----------------------------------

Memory Allocation and Usage
 - it shouldn't use too much. All memory of the userui is mlock()'d so it is
   not swapped out to disk. It shouldn't try to allocate huge amounts of memory
   outside of your prepare() function as this will starve TuxOnIce of
   memory for IO. A resource limit is enforced while suspending so excessive
   allocations should hopefully return with ENOMEM, but you should avoid this
   in the first place.

Disk access
 - Big no no. Do *NOT* try to access the disk whilst suspending as this will
   most likely corrupt the suspend image. Resource limits should cause file
   opening attempts to fail. If you want to opening a /proc entry or something
   not linked to a disk, do it in prepare().

Forking or threading
 - Don't fork mid-suspend. Resource limits will probably ensure that it fails.
   You can create forks or threads in prepare().  It should be safe so long as
   all threads follow these same rules.

Exiting
 - Exiting before the suspend/resume cycle has finished may corrupt the image.
   Don't try it. Signal handlers are installed to catch most common signals and
   simply sleep the process for a while.

Certain syscalls
 - It has been noted that calling select() or poll() to wait for data on a
   socket can be detrimental to suspending (causing things like several-second
   hangs whilst "Eating memory").

Minimalism is good - the process shouldn't do too much other than play with its
own memory, respond to events and dump stuff to display.