summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Brinkmann <marcus@gnu.org>2002-09-08 21:55:59 +0000
committerMarcus Brinkmann <marcus@gnu.org>2002-09-08 21:55:59 +0000
commit18cfa8b70ce9a6a3572908115f98211f3fa9a367 (patch)
tree42fd94dea9b27bb7020154a39a834429e936a560
parent187b5b4b28eba6990f7e43a5288a71b62a271dd9 (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/ChangeLog52
-rw-r--r--libcons/Makefile2
-rw-r--r--libcons/cons-lookup.c97
-rw-r--r--libcons/cons-switch.c82
-rw-r--r--libcons/cons.h124
-rw-r--r--libcons/dir-changed.c35
-rw-r--r--libcons/file-changed.c6
-rw-r--r--libcons/init-init.c10
-rw-r--r--libcons/vcons-add.c17
-rw-r--r--libcons/vcons-close.c38
-rw-r--r--libcons/vcons-destroy.c52
-rw-r--r--libcons/vcons-open.c39
-rw-r--r--libcons/vcons-remove.c9
-rw-r--r--utils/ChangeLog17
-rw-r--r--utils/console-ncurses.c178
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 ();