diff options
author | Marcus Brinkmann <marcus@gnu.org> | 2002-09-08 21:55:59 +0000 |
---|---|---|
committer | Marcus Brinkmann <marcus@gnu.org> | 2002-09-08 21:55:59 +0000 |
commit | 18cfa8b70ce9a6a3572908115f98211f3fa9a367 (patch) | |
tree | 42fd94dea9b27bb7020154a39a834429e936a560 | |
parent | 187b5b4b28eba6990f7e43a5288a71b62a271dd9 (diff) |
libcons/
2002-09-09 Marcus Brinkmann <marcus@gnu.org>
* vcons-remove.c: New file.
* Makefile (SRCS): Add vcons-destroy.c.
* cons.h: New type vcons_list_t.
(struct vcons_list): New structure.
(struct cons_notify): Remove VCONS member.
(struct vcons): Remove members NEXT, PREV and NOTIFY. Add the
notify structure to the top to make it possible to use a vcons as
a port. New member VCONS_ENTRY.
(struct cons): Change type of members vcons_list and vcons_last to
vcons_list_t. Remove member active.
(cons_vcons_add): Change prototype to match new definition.
(cons_vcons_remove): Likewise.
(cons_switch): Likewise.
(cons_lookup): Likewise.
(cons_vcons_open): Likewise.
(cons_vcons_destroy): New prototype.
* cons-lookup.c (cons_lookup): Change type of R_VCONS argument
vcons_list_t. Change type of previous_vcons and vcons variables
to vcons_list_t. Append _entry to all these variables.
Don't allocate and initialize a vcons_t, but a vcons_list_t.
After this has been added to the list, call cons_vcons_add.
* cons-switch.c: Do not include <error.h>
(cons_switch): Add arguments ACTIVE_ID and R_VCONS. New variable
ERR and VCONS_ENTRY. Remove variable ACTIVE. Do not keep track
of active console. Instead, look it up using ACTIVE_ID. Lock the
returned console. Call cons_vcons_open, not cons_vcons_activate.
* dir-changed.c (add_one): Change VCONS to VCONS_ENTRY and its
type from vcons_t to vcons_list_t to follow cons_lookup change.
(lookup_one): Likewise.
(cons_S_dir_changed): Likewise.
* file-changed.c (cons_S_file_changed): Cast NOTIFY to VCONS.
Check that NOTIFY->cons is not set instead that NOTIFY->vcons is.
* init-init.c (cons_init): Pass cons_vcons_destroy as
clean_routine to ports_create_class.
Don't initialize CONS->active, nor DIR_NOTIFY_PORT->vcons.
* vcons-add.c (cons_vcons_add): Change argument VCONS to CONS and
VCONS_ENTRY. Don't do anything here (the user must implement it
all).
* vcons-close.c: Don't include <errno.h>, <unistd.h>, <stdio.h>,
<sys/mman.h>, <sys/fcntl.h>, <mach.h>. Include <assert.h>,
<hurd/ports.h> and <cthreads.h>.
(cons_vcons_close): Clear VCONS->vcons_entry->vcons. Derefence
and destroy VCONS.
* vcons-open.c (cons_vcons_open): Change arguments from VCONS to
CONS, VCONS_ENTRY and R_VCONS. New variable VCONS. Set up VCONS
as a port, and request notification messages on that.
* vcons-remove.c: Do not include <errno.h>.
(cons_vcons_remove): Assert that VCONS_ENTRY does not have an open
VCONS.
utils/
2002-09-09 Marcus Brinkmann <marcus@gnu.org>
* console-ncurses.c: New global variable global_lock.
(main): Initialize global_lock.
(cons_vcons_activate): Removed.
(console_switch): New function.
(cons_vcons_add): New function.
(input_loop): Call console_switch, not cons_switch. Do not take
active_vcons lock but global_lock.
(cons_vcons_update): Take global lock.
(cons_vcons_set_cursor_pos): Likewise.
(cons_vcons_set_cursor_status): Likewise.
(cons_vcons_scroll): Likewise.
(cons_vcons_write): Likewise.
(cons_vcons_beep): Likewise.
(cons_vcons_flash): Likewise.
-rw-r--r-- | libcons/ChangeLog | 52 | ||||
-rw-r--r-- | libcons/Makefile | 2 | ||||
-rw-r--r-- | libcons/cons-lookup.c | 97 | ||||
-rw-r--r-- | libcons/cons-switch.c | 82 | ||||
-rw-r--r-- | libcons/cons.h | 124 | ||||
-rw-r--r-- | libcons/dir-changed.c | 35 | ||||
-rw-r--r-- | libcons/file-changed.c | 6 | ||||
-rw-r--r-- | libcons/init-init.c | 10 | ||||
-rw-r--r-- | libcons/vcons-add.c | 17 | ||||
-rw-r--r-- | libcons/vcons-close.c | 38 | ||||
-rw-r--r-- | libcons/vcons-destroy.c | 52 | ||||
-rw-r--r-- | libcons/vcons-open.c | 39 | ||||
-rw-r--r-- | libcons/vcons-remove.c | 9 | ||||
-rw-r--r-- | utils/ChangeLog | 17 | ||||
-rw-r--r-- | utils/console-ncurses.c | 178 |
15 files changed, 463 insertions, 295 deletions
diff --git a/libcons/ChangeLog b/libcons/ChangeLog index c9b7a5bf..ee8a9ec6 100644 --- a/libcons/ChangeLog +++ b/libcons/ChangeLog @@ -1,3 +1,55 @@ +2002-09-09 Marcus Brinkmann <marcus@gnu.org> + + * vcons-remove.c: New file. + * Makefile (SRCS): Add vcons-destroy.c. + * cons.h: New type vcons_list_t. + (struct vcons_list): New structure. + (struct cons_notify): Remove VCONS member. + (struct vcons): Remove members NEXT, PREV and NOTIFY. Add the + notify structure to the top to make it possible to use a vcons as + a port. New member VCONS_ENTRY. + (struct cons): Change type of members vcons_list and vcons_last to + vcons_list_t. Remove member active. + (cons_vcons_add): Change prototype to match new definition. + (cons_vcons_remove): Likewise. + (cons_switch): Likewise. + (cons_lookup): Likewise. + (cons_vcons_open): Likewise. + (cons_vcons_destroy): New prototype. + * cons-lookup.c (cons_lookup): Change type of R_VCONS argument + vcons_list_t. Change type of previous_vcons and vcons variables + to vcons_list_t. Append _entry to all these variables. + Don't allocate and initialize a vcons_t, but a vcons_list_t. + After this has been added to the list, call cons_vcons_add. + * cons-switch.c: Do not include <error.h> + (cons_switch): Add arguments ACTIVE_ID and R_VCONS. New variable + ERR and VCONS_ENTRY. Remove variable ACTIVE. Do not keep track + of active console. Instead, look it up using ACTIVE_ID. Lock the + returned console. Call cons_vcons_open, not cons_vcons_activate. + * dir-changed.c (add_one): Change VCONS to VCONS_ENTRY and its + type from vcons_t to vcons_list_t to follow cons_lookup change. + (lookup_one): Likewise. + (cons_S_dir_changed): Likewise. + * file-changed.c (cons_S_file_changed): Cast NOTIFY to VCONS. + Check that NOTIFY->cons is not set instead that NOTIFY->vcons is. + * init-init.c (cons_init): Pass cons_vcons_destroy as + clean_routine to ports_create_class. + Don't initialize CONS->active, nor DIR_NOTIFY_PORT->vcons. + * vcons-add.c (cons_vcons_add): Change argument VCONS to CONS and + VCONS_ENTRY. Don't do anything here (the user must implement it + all). + * vcons-close.c: Don't include <errno.h>, <unistd.h>, <stdio.h>, + <sys/mman.h>, <sys/fcntl.h>, <mach.h>. Include <assert.h>, + <hurd/ports.h> and <cthreads.h>. + (cons_vcons_close): Clear VCONS->vcons_entry->vcons. Derefence + and destroy VCONS. + * vcons-open.c (cons_vcons_open): Change arguments from VCONS to + CONS, VCONS_ENTRY and R_VCONS. New variable VCONS. Set up VCONS + as a port, and request notification messages on that. + * vcons-remove.c: Do not include <errno.h>. + (cons_vcons_remove): Assert that VCONS_ENTRY does not have an open + VCONS. + 2002-08-28 Marcus Brinkmann <marcus@gnu.org> * file-changed.c (cons_S_file_changed): Take NEW_CUR_LINE modulo diff --git a/libcons/Makefile b/libcons/Makefile index a6d60419..a7fe6bf8 100644 --- a/libcons/Makefile +++ b/libcons/Makefile @@ -22,7 +22,7 @@ libname = libcons SRCS= demuxer.c init-init.c init-loop.c opts-version.c extra-version.c \ dir-changed.c file-changed.c opts-std-startup.c cons-lookup.c \ cons-switch.c vcons-remove.c vcons-add.c vcons-open.c \ - vcons-close.c vcons-refresh.c + vcons-close.c vcons-destroy.c vcons-refresh.c LCLHDRS = priv.h mutations.h installhdrs = cons.h diff --git a/libcons/cons-lookup.c b/libcons/cons-lookup.c index f3bdabef..d91cc3ce 100644 --- a/libcons/cons-lookup.c +++ b/libcons/cons-lookup.c @@ -24,16 +24,16 @@ #include "cons.h" -/* Lookup the virtual console with number ID in the console CONS, - acquire a reference for it, and return it in R_VCONS. If CREATE is - true, the virtual console will be created if it doesn't exist yet. - If CREATE is true, and ID 0, the first free virtual console id is +/* Lookup the virtual console entry with number ID in the console + CONS, and return it in R_VCONS_ENTRY. If CREATE is true, the + virtual console entry will be created if it doesn't exist yet. If + CREATE is true, and ID 0, the first free virtual console id is used. CONS must be locked. */ error_t -cons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons) +cons_lookup (cons_t cons, int id, int create, vcons_list_t *r_vcons_entry) { - vcons_t previous_vcons = 0; - vcons_t vcons; + vcons_list_t previous_vcons_entry = 0; + vcons_list_t vcons_entry; if (!id && !create) return EINVAL; @@ -42,13 +42,13 @@ cons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons) { if (cons->vcons_list && cons->vcons_list->id <= id) { - previous_vcons = cons->vcons_list; - while (previous_vcons->next && previous_vcons->next->id <= id) - previous_vcons = previous_vcons->next; - if (previous_vcons->id == id) + previous_vcons_entry = cons->vcons_list; + while (previous_vcons_entry->next + && previous_vcons_entry->next->id <= id) + previous_vcons_entry = previous_vcons_entry->next; + if (previous_vcons_entry->id == id) { - /* previous_vcons->refcnt++; */ - *r_vcons = previous_vcons; + *r_vcons_entry = previous_vcons_entry; return 0; } } @@ -60,75 +60,48 @@ cons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons) id = 1; if (cons->vcons_list && cons->vcons_list->id == 1) { - previous_vcons = cons->vcons_list; - while (previous_vcons && previous_vcons->id == id) + previous_vcons_entry = cons->vcons_list; + while (previous_vcons_entry && previous_vcons_entry->id == id) { id++; - previous_vcons = previous_vcons->next; + previous_vcons_entry = previous_vcons_entry->next; } } } - vcons = calloc (1, sizeof (struct vcons)); - if (!vcons) - { - mutex_unlock (&vcons->cons->lock); - return ENOMEM; - } - vcons->cons = cons; - /* vcons->refcnt = 1; */ - vcons->id = id; - mutex_init (&vcons->lock); - vcons->input = -1; - vcons->display = MAP_FAILED; - vcons->notify = NULL; + vcons_entry = calloc (1, sizeof (struct vcons_list)); + if (!vcons_entry) + return ENOMEM; -#if 0 - err = display_create (&vcons->display, cons->encoding ?: DEFAULT_ENCODING, - cons->foreground, cons->background); - if (err) - { - free (vcons->name); - free (vcons); - return err; - } - - err = input_create (&vcons->input, cons->encoding ?: DEFAULT_ENCODING); - if (err) - { - display_destroy (vcons->display); - free (vcons->name); - free (vcons); - return err; - } -#endif - - cons_vcons_add (vcons); + vcons_entry->id = id; + vcons_entry->vcons = NULL; /* Insert the virtual console into the doubly linked list. */ - if (previous_vcons) + if (previous_vcons_entry) { - vcons->prev = previous_vcons; - if (previous_vcons->next) + vcons_entry->prev = previous_vcons_entry; + if (previous_vcons_entry->next) { - previous_vcons->next->prev = vcons; - vcons->next = previous_vcons->next; + previous_vcons_entry->next->prev = vcons_entry; + vcons_entry->next = previous_vcons_entry->next; } else - cons->vcons_last = vcons; - previous_vcons->next = vcons; + cons->vcons_last = vcons_entry; + previous_vcons_entry->next = vcons_entry; } else { if (cons->vcons_list) { - cons->vcons_list->prev = vcons; - vcons->next = cons->vcons_list; + cons->vcons_list->prev = vcons_entry; + vcons_entry->next = cons->vcons_list; } else - cons->vcons_last = vcons; - cons->vcons_list = vcons; + cons->vcons_last = vcons_entry; + cons->vcons_list = vcons_entry; } - *r_vcons = vcons; + + cons_vcons_add (cons, vcons_entry); + *r_vcons_entry = vcons_entry; return 0; } diff --git a/libcons/cons-switch.c b/libcons/cons-switch.c index f2b72daf..d9aa64af 100644 --- a/libcons/cons-switch.c +++ b/libcons/cons-switch.c @@ -19,77 +19,65 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ #include <errno.h> -#include <error.h> #include <assert.h> #include "cons.h" -/* Switch the active console in CONS to ID or the current one plus - DELTA. This will call back into the user code by doing a - cons_vcons_activate. */ +/* Open the virtual console ID or the ACTIVE_ID plus DELTA one in CONS + and return it in R_VCONS, which will be locked. */ error_t -cons_switch (cons_t cons, int id, int delta) +cons_switch (cons_t cons, int active_id, int id, int delta, vcons_t *r_vcons) { - vcons_t vcons = NULL; - vcons_t active; + error_t err = 0; + vcons_list_t vcons_entry = NULL; if (!id && !delta) return 0; mutex_lock (&cons->lock); - active = cons->active; + vcons_entry = cons->vcons_list; + while (vcons_entry && vcons_entry->id != (id ?: active_id)) + vcons_entry = vcons_entry->next; - if (!id && !active) + if (!id && vcons_entry) { - mutex_unlock (&cons->lock); - return EINVAL; - } - - if (id) - { - vcons = cons->vcons_list; - while (vcons && vcons->id != id) - vcons = vcons->next; - } - else if (delta > 0) - { - vcons = cons->active; - while (delta-- > 0) + if (delta > 0) { - vcons = vcons->next; - if (!vcons) - vcons = cons->vcons_list; + while (delta-- > 0) + { + vcons_entry = vcons_entry->next; + if (!vcons_entry) + vcons_entry = cons->vcons_list; + } } - } - else - { - assert (delta < 0); - while (delta++ < 0) + else { - vcons = vcons->prev; - if (!vcons) - vcons = cons->vcons_last; + assert (delta < 0); + while (delta++ < 0) + { + vcons_entry = vcons_entry->prev; + if (!vcons_entry) + vcons_entry = cons->vcons_last; + } } } - - if (!vcons) + if (!vcons_entry) { mutex_unlock (&cons->lock); return ESRCH; } - if (vcons != active) + if (vcons_entry->vcons) { - error_t err = cons_vcons_activate (vcons); - if (err) - { - mutex_unlock (&cons->lock); - return err; - } - - cons->active = vcons; - cons_vcons_refresh (vcons); + *r_vcons = vcons_entry->vcons; + mutex_lock (&vcons_entry->vcons->lock); + } + else + { + err = cons_vcons_open (cons, vcons_entry, r_vcons); + if (!err) + vcons_entry->vcons = *r_vcons; } mutex_unlock (&cons->lock); - return 0; + return err; } diff --git a/libcons/cons.h b/libcons/cons.h index 7966657b..e7484db5 100644 --- a/libcons/cons.h +++ b/libcons/cons.h @@ -28,23 +28,51 @@ #include <hurd/console.h> -typedef struct vcons *vcons_t; typedef struct cons *cons_t; +typedef struct vcons_list *vcons_list_t; +typedef struct vcons *vcons_t; typedef struct cons_notify *cons_notify_t; +struct vcons_list +{ + cons_t cons; + vcons_list_t next; + vcons_list_t prev; + + /* The ID of the virtual console entry in the list. */ + int id; + + /* The opened vcons port on which we receive notifications. */ + vcons_t vcons; +}; + +struct cons_notify +{ + struct port_info pi; + + /* This is set for the dir notification port. */ + cons_t cons; +}; + struct vcons { - vcons_t next; - vcons_t prev; + /* This must come first for the port info structure. */ + struct cons_notify notify; + + /* These elements are static from creation time. */ cons_t cons; + vcons_list_t vcons_entry; int id; + /* The lock that protects all other members. */ struct mutex lock; + /* The FD of the input node. */ int input; + + /* The shared memory of the display. */ struct cons_display *display; size_t display_size; - cons_notify_t notify; struct { @@ -82,9 +110,8 @@ struct cons /* Protects the cons structure and the linked list in VCONS_LIST. */ struct mutex lock; - vcons_t vcons_list; - vcons_t vcons_last; - vcons_t active; + vcons_list_t vcons_list; + vcons_list_t vcons_last; struct port_class *port_class; struct port_bucket *port_bucket; @@ -93,23 +120,12 @@ struct cons int slack; }; -struct cons_notify -{ - struct port_info pi; - - /* This is set for the dir notification port. */ - cons_t cons; - - /* This is set for the file notification ports. */ - vcons_t vcons; -}; - /* The user must define this variable. Set this to the name of the console client. */ extern const char *cons_client_name; -/* The user must define this variables. Set this to be the client +/* The user must define this variable. Set this to be the client version number. */ extern const char *cons_client_version; @@ -133,10 +149,31 @@ void cons_vcons_set_cursor_status (vcons_t vcons, uint32_t status); /* The user must define this function. Scroll the content of virtual console VCONS, which is locked, up by DELTA if DELTA is positive or - down by -DELTA if DELTA is negative. This call will be immediately - followed by corresponding cons_vcons_write calls to fill the - resulting gap on the screen, and VCONS will be looked throughout - the whole time. */ + down by -DELTA if DELTA is negative. DELTA will never be zero, and + the absolute value if DELTA will be smaller than or equal to the + height of the screen matrix. + + This call will be immediately followed by corresponding + cons_vcons_write calls to fill the resulting gap on the screen, and + VCONS will be looked throughout the whole time. The purpose of the + function is two-fold: It is called with an absolute value of DELTA + smaller than the screen height to perform scrolling. It is called + with an absolute value of DELTA equal to the screen height to + prepare a full refresh of the screen. In the latter case the user + should not really perform any scrolling. Instead it might + deallocate limited resources (like display glyph slots and palette + colors) if that helps to perform the subsequent write. It goes + without saying that the same deallocation, if any, should be + performed on the area that will be filled with the scrolled in + content. + + XXX Possibly need a function to invalidate scrollback buffer, or in + general to signal a switch of the console so state can be reset. + Only do this if we make guarantees about validity of scrollback + buffer, of course. + + The driver is allowed to delay the effect of this operation until + the UPDATE function is called. */ void cons_vcons_scroll (vcons_t vcons, int delta); /* The user may define this function. Make the changes from @@ -157,21 +194,22 @@ void cons_vcons_beep (vcons_t vcons); void cons_vcons_flash (vcons_t vcons); /* The user must define this function. It is called whenever a - virtual console is selected to be the active one. */ + virtual console is selected to be the active one. It is the user's + responsibility to close the console at some later time. */ error_t cons_vcons_activate (vcons_t vcons); -/* The user may define this function. It is called whenever a - virtual console is added. VCONS->cons is locked. */ -void cons_vcons_add (vcons_t vcons); +/* The user may define this function. It is called after a + virtual console entry was added. CONS is locked. */ +void cons_vcons_add (cons_t cons, vcons_list_t vcons_entry); -/* The user may define this function. It is called whenever a - virtual console is removed. VCONS->cons is locked. */ -void cons_vcons_remove (vcons_t vcons); +/* The user may define this function. It is called just before a + virtual console entry is removed. CONS is locked. */ +void cons_vcons_remove (cons_t cons, vcons_list_t vcons_entry); -/* Switch the active console in CONS to ID or the current one plus - DELTA. This will call back into the user code by doing a - cons_vcons_activate. */ -error_t cons_switch (cons_t cons, int id, int delta); +/* Open the virtual console ID or the ACTIVE_ID plus DELTA one in CONS + and return it in R_VCONS. */ +error_t cons_switch (cons_t cons, int active_id, int id, int delta, + vcons_t *r_vcons); extern const struct argp cons_startup_argp; @@ -184,18 +222,22 @@ void cons_server_loop (void); int cons_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp); /* Lookup the virtual console with number ID in the console CONS, - acquire a reference for it, and return it in R_VCONS. If CREATE is - true, the virtual console will be created if it doesn't exist yet. - If CREATE is true, and ID 0, the first free virtual console id is - used. CONS must be locked. */ -error_t cons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons); + acquire a reference for it, and return its list entry in R_VCONS. + If CREATE is true, the virtual console will be created if it + doesn't exist yet. If CREATE is true, and ID 0, the first free + virtual console id is used. CONS must be locked. */ +error_t cons_lookup (cons_t cons, int id, int create, vcons_list_t *r_vcons); -/* Open the virtual console VCONS. VCONS->cons is locked. */ -error_t cons_vcons_open (vcons_t vcons); +/* Open the virtual console for VCONS_ENTRY. CONS is locked. */ +error_t cons_vcons_open (cons_t cons, vcons_list_t vcons_entry, + vcons_t *r_vcons); /* Close the virtual console VCONS. VCONS->cons is locked. */ void cons_vcons_close (vcons_t vcons); +/* Destroy the virtual console VCONS. */ +void cons_vcons_destroy (void *port); + /* Redraw the virtual console VCONS, which is locked. */ void cons_vcons_refresh (vcons_t vcons); diff --git a/libcons/dir-changed.c b/libcons/dir-changed.c index 15b466a6..e1997d0f 100644 --- a/libcons/dir-changed.c +++ b/libcons/dir-changed.c @@ -27,7 +27,7 @@ #include "cons.h" #include "fs_notify_S.h" - + static error_t add_one (cons_t cons, char *name) { @@ -38,14 +38,14 @@ add_one (cons_t cons, char *name) nr = strtoul (name, &tail, 10); if (!errno && *tail == '\0' && nr > 0) { - vcons_t vcons; - return cons_lookup (cons, nr, 1, &vcons); + vcons_list_t vcons_entry; + return cons_lookup (cons, nr, 1, &vcons_entry); } return 0; } static error_t -lookup_one (cons_t cons, char *name, vcons_t *vcons) +lookup_one (cons_t cons, char *name, vcons_list_t *vcons_entry) { unsigned long int nr; char *tail; @@ -53,11 +53,11 @@ lookup_one (cons_t cons, char *name, vcons_t *vcons) errno = 0; nr = strtoul (name, &tail, 10); if (!errno && *tail == '\0' && nr > 0) - return cons_lookup (cons, nr, 0, vcons); + return cons_lookup (cons, nr, 0, vcons_entry); return 0; } - + kern_return_t cons_S_dir_changed (cons_notify_t notify, natural_t tickno, dir_changed_type_t change, string_t name) @@ -100,22 +100,21 @@ cons_S_dir_changed (cons_notify_t notify, natural_t tickno, break; case DIR_CHANGED_UNLINK: { - vcons_t vcons; - err = lookup_one (cons, name, &vcons); + vcons_list_t vcons_entry; + err = lookup_one (cons, name, &vcons_entry); if (!err) { - cons_vcons_remove (vcons); - if (vcons->prev) - vcons->prev->next = vcons->next; + cons_vcons_remove (cons, vcons_entry); + if (vcons_entry->prev) + vcons_entry->prev->next = vcons_entry->next; else - cons->vcons_list = vcons->next; - if (vcons->next) - vcons->next->prev = vcons->prev; + cons->vcons_list = vcons_entry->next; + if (vcons_entry->next) + vcons_entry->next->prev = vcons_entry->prev; else - cons->vcons_last = vcons->prev; + cons->vcons_last = vcons_entry->prev; - /* XXX Destroy the state. */ - free (vcons); + free (vcons_entry); } } break; @@ -123,7 +122,7 @@ cons_S_dir_changed (cons_notify_t notify, natural_t tickno, default: assert ("Unexpected dir-changed type."); mutex_unlock (&cons->lock); - return EINVAL; + return EINVAL; } mutex_unlock (&cons->lock); return 0; diff --git a/libcons/file-changed.c b/libcons/file-changed.c index a681d626..9d7a066b 100644 --- a/libcons/file-changed.c +++ b/libcons/file-changed.c @@ -30,13 +30,11 @@ cons_S_file_changed (cons_notify_t notify, natural_t tickno, off_t start, off_t end) { error_t err = 0; - vcons_t vcons; + vcons_t vcons = (vcons_t) notify; - if (!notify || !notify->vcons) + if (!notify || notify->cons) return EOPNOTSUPP; - vcons = notify->vcons; - mutex_lock (&vcons->lock); switch (change) { diff --git a/libcons/init-init.c b/libcons/init-init.c index e84f0e67..731d819e 100644 --- a/libcons/init-init.c +++ b/libcons/init-init.c @@ -18,7 +18,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ - #include <errno.h> #include <malloc.h> @@ -30,9 +29,10 @@ #include "cons.h" #include "priv.h" - struct port_bucket *cons_port_bucket; - struct port_class *cons_port_class; +struct port_bucket *cons_port_bucket; +struct port_class *cons_port_class; + error_t cons_init (void) { @@ -45,7 +45,7 @@ cons_init (void) if (!cons_port_bucket) return errno; - cons_port_class = ports_create_class (NULL, NULL); + cons_port_class = ports_create_class (cons_vcons_destroy, NULL); if (!cons_port_class) return errno; @@ -56,7 +56,6 @@ cons_init (void) mutex_init (&cons->lock); cons->vcons_list = NULL; cons->vcons_last = NULL; - cons->active = NULL; cons->dir = opendir (_cons_file); cons->slack = _cons_slack; if (!cons->dir) @@ -83,7 +82,6 @@ cons_init (void) return err; } dir_notify_port->cons = cons; - dir_notify_port->vcons = NULL; dir_notify = ports_get_right (dir_notify_port); err = dir_notice_changes (cons->dirport, dir_notify, diff --git a/libcons/vcons-add.c b/libcons/vcons-add.c index cc7717f6..1a6eb204 100644 --- a/libcons/vcons-add.c +++ b/libcons/vcons-add.c @@ -22,22 +22,9 @@ #include "cons.h" -/* The virtual console VCONS was just added. VCONS->cons is +/* The virtual console entry VCONS_ENTRY was just added. CONS is locked. */ void -cons_vcons_add (vcons_t vcons) +cons_vcons_add (cons_t cons, vcons_list_t vcons_entry) { - error_t err; - - /* The first console added will be activated automatically. */ - if (vcons->cons->active) - return; - - /* Forward the activation request to the user. */ - err = cons_vcons_activate (vcons); - if (!err) - { - vcons->cons->active = vcons; - cons_vcons_refresh (vcons); - } } diff --git a/libcons/vcons-close.c b/libcons/vcons-close.c index 584c3e61..33a38982 100644 --- a/libcons/vcons-close.c +++ b/libcons/vcons-close.c @@ -18,34 +18,28 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ -#include <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <sys/mman.h> -#include <sys/fcntl.h> +#include <assert.h> #include <hurd.h> -#include <mach.h> +#include <hurd/ports.h> +#include <cthreads.h> #include "cons.h" -/* Close the virtual console VCONS. VCONS->cons is locked. */ +/* Close the virtual console VCONS. */ void cons_vcons_close (vcons_t vcons) { - if (vcons->input >= 0) - { - close (vcons->input); - vcons->input = -1; - } - if (vcons->display != MAP_FAILED) - { - munmap (vcons->display, vcons->display_size); - vcons->display = MAP_FAILED; - } - if (vcons->notify) - { - ports_destroy_right (vcons->notify); - vcons->notify = NULL; - } + cons_t cons = vcons->cons; + vcons_list_t vcons_entry = vcons->vcons_entry; + + mutex_lock (&cons->lock); + /* The same virtual console should never be opened twice. */ + assert (vcons_entry->vcons == vcons); + vcons_entry->vcons = NULL; + mutex_unlock (&cons->lock); + + /* Destroy the port. */ + ports_port_deref (vcons); + ports_destroy_right (vcons); } diff --git a/libcons/vcons-destroy.c b/libcons/vcons-destroy.c new file mode 100644 index 00000000..ca1c5c37 --- /dev/null +++ b/libcons/vcons-destroy.c @@ -0,0 +1,52 @@ +/* vcons-destroy.c - Clean up the resources for a virtual console. + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd 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, or (at + your option) any later version. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/mman.h> +#include <sys/fcntl.h> + +#include <hurd.h> +#include <mach.h> + +#include "cons.h" + +/* Destroy the virtual console VCONS. */ +void +cons_vcons_destroy (void *port) +{ + cons_notify_t notify = (cons_notify_t) port; + vcons_t vcons = (vcons_t) port; + + if (notify->cons) + return; + + if (vcons->input >= 0) + { + close (vcons->input); + vcons->input = -1; + } + if (vcons->display != MAP_FAILED) + { + munmap (vcons->display, vcons->display_size); + vcons->display = MAP_FAILED; + } +} diff --git a/libcons/vcons-open.c b/libcons/vcons-open.c index 7256b4c8..0d826b63 100644 --- a/libcons/vcons-open.c +++ b/libcons/vcons-open.c @@ -29,9 +29,10 @@ #include "cons.h" -/* Open the virtual console VCONS. VCONS->cons is locked. */ +/* Open the virtual console for VCONS_ENTRY. CONS is locked. + Afterwards, R_VCONS will be locked. */ error_t -cons_vcons_open (vcons_t vcons) +cons_vcons_open (cons_t cons, vcons_list_t vcons_entry, vcons_t *r_vcons) { error_t err = 0; char *name; @@ -40,12 +41,23 @@ cons_vcons_open (vcons_t vcons) int fd = -1; struct stat statbuf; mach_port_t notify = MACH_PORT_NULL; + vcons_t vcons; - if (asprintf (&name, "%u", vcons->id) < 0) + if (asprintf (&name, "%u", vcons_entry->id) < 0) return err; + /* Set up the port we receive notification messages on. */ + err = ports_create_port (cons_port_class, cons_port_bucket, + sizeof (*vcons), &vcons); + if (err) + goto err; + vcons->notify.cons = NULL; + vcons->cons = cons; + vcons->vcons_entry = vcons_entry; + vcons->id = vcons_entry->id; + /* Open the directory port of the virtual console. */ - vconsp = file_name_lookup_under (vcons->cons->dirport, name, + vconsp = file_name_lookup_under (cons->dirport, name, O_DIRECTORY | O_RDONLY, 0); if (vconsp == MACH_PORT_NULL) { @@ -116,23 +128,19 @@ cons_vcons_open (vcons_t vcons) vcons->state.changes.buffer = ((uint32_t *) vcons->display) + vcons->display->changes.buffer; - /* Set up the port we receive notification messages on. */ - err = ports_create_port (cons_port_class, cons_port_bucket, - sizeof (*vcons->notify), &vcons->notify); - if (err) - goto err; - vcons->notify->cons = NULL; - vcons->notify->vcons = vcons; - /* Request notification messages. */ - notify = ports_get_right (vcons->notify); + notify = ports_get_right (vcons); mach_port_set_qlimit (mach_task_self (), notify, 1); /* When this succeeds, we will immediately receive notification messages for this virtual console. */ + mutex_lock (&vcons->lock); err = file_notice_changes (file, notify, MACH_MSG_TYPE_MAKE_SEND); if (!err) - goto out; + { + *r_vcons = vcons; + goto out; + } err: if (vcons->input >= 0) @@ -148,8 +156,9 @@ cons_vcons_open (vcons_t vcons) if (notify) { mach_port_deallocate (mach_task_self (), notify); - vcons->notify = MACH_PORT_NULL; + ports_port_deref (vcons); } + ports_destroy_right (vcons); out: if (fd > 0) close (fd); diff --git a/libcons/vcons-remove.c b/libcons/vcons-remove.c index 56fb34ab..34b31d6f 100644 --- a/libcons/vcons-remove.c +++ b/libcons/vcons-remove.c @@ -18,15 +18,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ -#include <errno.h> #include <assert.h> #include "cons.h" -/* The virtual console VCONS is going to be removed. VCONS->cons is - locked. */ +/* The virtual console VCONS_ENTRY is going to be removed. + VCONS_ENTRY->cons is locked. */ void -cons_vcons_remove (vcons_t vcons) +cons_vcons_remove (cons_t cons, vcons_list_t vcons_entry) { - assert (vcons != vcons->cons->active); + assert (!vcons_entry->vcons); } diff --git a/utils/ChangeLog b/utils/ChangeLog index 904e5bd6..e5562a10 100644 --- a/utils/ChangeLog +++ b/utils/ChangeLog @@ -1,3 +1,20 @@ +2002-09-09 Marcus Brinkmann <marcus@gnu.org> + + * console-ncurses.c: New global variable global_lock. + (main): Initialize global_lock. + (cons_vcons_activate): Removed. + (console_switch): New function. + (cons_vcons_add): New function. + (input_loop): Call console_switch, not cons_switch. Do not take + active_vcons lock but global_lock. + (cons_vcons_update): Take global lock. + (cons_vcons_set_cursor_pos): Likewise. + (cons_vcons_set_cursor_status): Likewise. + (cons_vcons_scroll): Likewise. + (cons_vcons_write): Likewise. + (cons_vcons_beep): Likewise. + (cons_vcons_flash): Likewise. + 2002-08-29 Marcus Brinkmann <marcus@gnu.org> * console-ncurses.c (main): Call endwin () before bailing out diff --git a/utils/console-ncurses.c b/utils/console-ncurses.c index 1f12ff3c..fb0b4190 100644 --- a/utils/console-ncurses.c +++ b/utils/console-ncurses.c @@ -259,24 +259,68 @@ ucs4_to_altchar (wchar_t chr, chtype *achr) return 1; } +struct mutex global_lock; static vcons_t active_vcons = NULL; error_t -cons_vcons_activate (vcons_t vcons) +console_switch (int id, int delta) { - error_t err; - - assert (vcons); - assert (vcons != active_vcons); + error_t err = 0; + int active_id; + cons_t cons; + vcons_t vcons; - err = cons_vcons_open (vcons); - if (err) - return err; + mutex_lock (&global_lock); + if (!active_vcons) + { + mutex_unlock (&global_lock); + return 0; + } + cons = active_vcons->cons; + active_id = active_vcons->id; + + /* We must give up our global lock before we can call back into + libcons. This is because cons_switch will lock CONS, and as + other functions in libcons lock CONS while calling back into our + functions which take the global lock (like cons_vcons_add), we + would deadlock. Because of this, we can not refer to our active + console directly, but we must refer to it by name (ID). XXX + Likewise, we can not really refer to CONS directly, but the + current implementation guarantees an eternal life span for + CONS. */ + mutex_unlock (&global_lock); + err = cons_switch (cons, active_id, id, delta, &vcons); + if (!err) + { + mutex_lock (&global_lock); + if (active_vcons != vcons) + { + cons_vcons_close (active_vcons); + active_vcons = vcons; + } + mutex_unlock (&vcons->lock); + mutex_unlock (&global_lock); + } + return err; +} - if (active_vcons) - cons_vcons_close (active_vcons); - active_vcons = vcons; - return 0; +void +cons_vcons_add (cons_t cons, vcons_list_t vcons_entry) +{ + error_t err = 0; + mutex_lock (&global_lock); + if (!active_vcons) + { + vcons_t vcons; + err = cons_vcons_open (cons, vcons_entry, &vcons); + if (!err) + { + vcons_entry->vcons = vcons; + active_vcons = vcons; + mutex_unlock (&vcons->lock); + } + } + mutex_unlock (&global_lock); } any_t @@ -331,8 +375,7 @@ input_loop (any_t unused) case '9': /* Avoid a dead lock. */ mutex_unlock (&ncurses_lock); - /* XXX: We ignore any error here. */ - cons_switch (active_vcons->cons, 1 + (ret - '1'), 0); + console_switch (1 + (ret - '1'), 0); mutex_lock (&ncurses_lock); break; default: @@ -373,9 +416,9 @@ input_loop (any_t unused) mutex_unlock (&ncurses_lock); if (size) { + mutex_lock (&global_lock); if (active_vcons) { - mutex_lock (&active_vcons->lock); do { ret = write (active_vcons->input, buf, size); @@ -386,8 +429,8 @@ input_loop (any_t unused) } } while (size && (ret != -1 || errno == EINTR)); - mutex_unlock (&active_vcons->lock); } + mutex_unlock (&global_lock); } } } @@ -466,45 +509,55 @@ mvwputsn (conchar_t *str, size_t len, off_t x, off_t y) void cons_vcons_update (vcons_t vcons) { - if (vcons != active_vcons) - return; - refresh (); + mutex_lock (&global_lock); + if (vcons == active_vcons) + refresh (); + mutex_unlock (&global_lock); } void cons_vcons_set_cursor_pos (vcons_t vcons, uint32_t col, uint32_t row) { - if (vcons != active_vcons) - return; - mutex_lock (&ncurses_lock); - move (row, col); - mutex_unlock (&ncurses_lock); + mutex_lock (&global_lock); + if (vcons == active_vcons) + { + mutex_lock (&ncurses_lock); + move (row, col); + mutex_unlock (&ncurses_lock); + } + mutex_unlock (&global_lock); } void cons_vcons_set_cursor_status (vcons_t vcons, uint32_t status) { - if (vcons != active_vcons) - return; - mutex_lock (&ncurses_lock); - curs_set (status ? (status == 1 ? 1 : 2) : 0); - mutex_unlock (&ncurses_lock); + mutex_lock (&global_lock); + if (vcons == active_vcons) + { + mutex_lock (&ncurses_lock); + curs_set (status ? (status == 1 ? 1 : 2) : 0); + mutex_unlock (&ncurses_lock); + } + mutex_unlock (&global_lock); } void cons_vcons_scroll (vcons_t vcons, int delta) { assert (delta >= 0); - if (vcons != active_vcons) - return; - - mutex_lock (&ncurses_lock); - idlok (stdscr, TRUE); - scrollok (stdscr, TRUE); - scrl (delta); - idlok (stdscr, FALSE); - scrollok (stdscr, FALSE); - mutex_unlock (&ncurses_lock); + + mutex_lock (&global_lock); + if (vcons == active_vcons) + { + mutex_lock (&ncurses_lock); + idlok (stdscr, TRUE); + scrollok (stdscr, TRUE); + scrl (delta); + idlok (stdscr, FALSE); + scrollok (stdscr, FALSE); + mutex_unlock (&ncurses_lock); + } + mutex_unlock (&global_lock); } void @@ -514,36 +567,42 @@ cons_vcons_write (vcons_t vcons, conchar_t *str, size_t length, int x; int y; - if (vcons != active_vcons) - return; - - mutex_lock (&ncurses_lock); - getyx (stdscr, y, x); - mvwputsn (str, length, col, row); - wmove (stdscr, y, x); - mutex_unlock (&ncurses_lock); + mutex_lock (&global_lock); + if (vcons == active_vcons) + { + mutex_lock (&ncurses_lock); + getyx (stdscr, y, x); + mvwputsn (str, length, col, row); + wmove (stdscr, y, x); + mutex_unlock (&ncurses_lock); + } + mutex_unlock (&global_lock); } void cons_vcons_beep (vcons_t vcons) { - if (vcons != active_vcons) - return; - - mutex_lock (&ncurses_lock); - beep (); - mutex_unlock (&ncurses_lock); + mutex_lock (&global_lock); + if (vcons == active_vcons) + { + mutex_lock (&ncurses_lock); + beep (); + mutex_unlock (&ncurses_lock); + } + mutex_unlock (&global_lock); } void cons_vcons_flash (vcons_t vcons) { - if (vcons != active_vcons) - return; - - mutex_lock (&ncurses_lock); - flash (); - mutex_unlock (&ncurses_lock); + mutex_lock (&global_lock); + if (vcons == active_vcons) + { + mutex_lock (&ncurses_lock); + flash (); + mutex_unlock (&ncurses_lock); + } + mutex_unlock (&global_lock); } @@ -557,6 +616,7 @@ main (int argc, char *argv[]) argp_parse (&cons_startup_argp, argc, argv, 0, 0, 0); mutex_init (&ncurses_lock); + mutex_init (&global_lock); initscr (); start_color (); |