home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
mitsch75.zip
/
scheme-7_5_17-src.zip
/
scheme-7.5.17
/
src
/
microcode
/
os2thrd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-01-02
|
7KB
|
285 lines
/* -*-C-*-
$Id: os2thrd.c,v 1.6 1999/01/02 06:11:34 cph Exp $
Copyright (c) 1994-1999 Massachusetts Institute of Technology
This program 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 of the License, or (at
your option) any later version.
This program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "os2.h"
#include "prims.h"
#include "errors.h"
#ifdef __IBMC__
#define HAVE_BEGINTHREAD
#endif
#ifdef __WATCOMC__
#include <process.h>
#define HAVE_BEGINTHREAD
#endif
#ifdef __EMX__
#define HAVE_BEGINTHREAD
#endif
extern void OS2_create_msg_queue (void);
extern ULONG APIENTRY OS2_subthread_exception_handler
(PEXCEPTIONREPORTRECORD, PEXCEPTIONREGISTRATIONRECORD, PCONTEXTRECORD,
PVOID);
TID
OS2_beginthread (thread_procedure_t procedure,
void * argument,
unsigned int stack_size)
{
ULONG ss
= ((stack_size < 0x2000)
? 0x2000
: ((stack_size + 0xfff) & (~0xfff)));
#ifdef HAVE_BEGINTHREAD
int result = (_beginthread (procedure, 0, ss, argument));
if (result < 0)
OS2_error_system_call (ERROR_MAX_THRDS_REACHED, syscall_beginthread);
return (result);
#else /* not HAVE_BEGINTHREAD */
TID tid;
STD_API_CALL (dos_create_thread,
((&tid), ((PFNTHREAD) procedure), ((ULONG) argument), 0, ss));
return (tid);
#endif /* not HAVE_BEGINTHREAD */
}
void
OS2_endthread (void)
{
DosUnsetExceptionHandler (THREAD_EXCEPTION_HANDLER ());
#ifdef HAVE_BEGINTHREAD
_endthread ();
#else
dos_exit (EXIT_THREAD, 0);
#endif
}
void
OS2_kill_thread (TID tid)
{
STD_API_CALL (dos_kill_thread, (tid));
}
TID
OS2_current_tid (void)
{
PTIB ptib;
PPIB ppib;
STD_API_CALL (dos_get_info_blocks, ((&ptib), (&ppib)));
return (ptib -> tib_ptib2 -> tib2_ultid);
}
#ifndef __IBMC__
#define MAX_TID 999
static thread_store_t * thread_store_array [MAX_TID + 1];
thread_store_t **
OS2_threadstore (void)
{
TID tid = (OS2_current_tid ());
if (tid > MAX_TID)
OS2_logic_error ("Unexpectedly large TID.");
return (& (thread_store_array [tid]));
}
#endif
PID OS2_scheme_pid;
TID OS2_scheme_tid;
static void thread_initialize_1 (qid_t);
static void restore_errors (void *);
static void signal_error (msg_t *);
static void ignore_error (msg_t *);
static void send_error (msg_t *);
void
OS2_initialize_scheme_thread (void)
{
SET_MSG_TYPE_LENGTH (mt_syscall_error, sm_syscall_error_t);
SET_MSG_TYPE_LENGTH (mt_error, sm_error_t);
SET_MSG_TYPE_LENGTH (mt_kill_request, sm_kill_request_t);
{
PTIB ptib;
PPIB ppib;
STD_API_CALL (dos_get_info_blocks, ((&ptib), (&ppib)));
OS2_scheme_pid = (ppib -> pib_ulpid);
OS2_scheme_tid = (ptib -> tib_ptib2 -> tib2_ultid);
}
thread_initialize_1 (QID_NONE);
(THREAD_ERROR_HOOK ()) = signal_error;
}
int
OS2_thread_initialize (PEXCEPTIONREGISTRATIONRECORD registration,
qid_t error_qid)
{
/* Every thread has a message queue, so that we can use message
dialogs to report fatal errors to the user. Otherwise, Scheme
will just die with no explanation. */
OS2_create_msg_queue ();
return (OS2_thread_initialize_1 (registration, error_qid));
}
int
OS2_thread_initialize_1 (PEXCEPTIONREGISTRATIONRECORD registration,
qid_t error_qid)
{
thread_initialize_1 (error_qid);
(registration -> ExceptionHandler) = OS2_subthread_exception_handler;
DosSetExceptionHandler (registration);
(THREAD_EXCEPTION_HANDLER ()) = registration;
(THREAD_ERROR_HOOK ()) = send_error;
return (setjmp (THREAD_ERROR_RESTART ()));
}
static void
thread_initialize_1 (qid_t error_qid)
{
(* (OS2_threadstore ())) = (OS_malloc (sizeof (thread_store_t)));
(THREAD_ERROR_QUEUE ()) = error_qid;
((THREAD_FATAL_ERROR_BUFFER ()) [0]) = '\0';
}
char *
OS2_thread_fatal_error_buffer (void)
{
/* The default buffer may get used if an error occurs very early in
a thread, before the regular error buffer is allocated. This can
easily happen in the Scheme thread, but shouldn't happen in the
other threads. */
static char default_buffer [1024] = "";
return
(((* (OS2_threadstore ())) == 0)
? default_buffer
: (THREAD_FATAL_ERROR_BUFFER ()));
}
int
OS2_error_message_p (msg_t * message)
{
msg_type_t type = (MSG_TYPE (message));
return ((type == mt_syscall_error) || (type == mt_error));
}
void
OS2_handle_error_message (msg_t * message)
{
(* (THREAD_ERROR_HOOK ())) (message);
}
void
OS2_ignore_errors (void)
{
error_hook_t * hp = (dstack_alloc (sizeof (error_hook_t)));
(*hp) = (THREAD_ERROR_HOOK ());
transaction_record_action (tat_always, restore_errors, hp);
(THREAD_ERROR_HOOK ()) = ignore_error;
}
static void
restore_errors (void * hp)
{
(THREAD_ERROR_HOOK ()) = (* ((error_hook_t *) hp));
}
void
OS2_error_system_call (int code, enum syscall_names name)
{
OS2_handle_error_message (OS2_make_syscall_error (code, name));
}
void
OS2_error_anonymous (void)
{
OS2_handle_error_message (OS2_make_error (ERR_EXTERNAL_RETURN));
}
void
OS2_error_unimplemented_primitive (void)
{
OS2_handle_error_message (OS2_make_error (ERR_UNDEFINED_PRIMITIVE));
}
void
OS2_error_out_of_channels (void)
{
OS2_handle_error_message (OS2_make_error (ERR_OUT_OF_FILE_HANDLES));
}
static void
signal_error (msg_t * message)
{
switch (MSG_TYPE (message))
{
case mt_syscall_error:
{
int code = (SM_SYSCALL_ERROR_CODE (message));
enum syscall_names name = (SM_SYSCALL_ERROR_NAME (message));
OS2_destroy_message (message);
error_system_call (code, name);
}
break;
case mt_error:
{
long code = (SM_ERROR_CODE (message));
OS2_destroy_message (message);
signal_error_from_primitive (code);
}
break;
default:
OS2_logic_error ("Non-error message passed to signal_error.");
break;
}
}
static void
ignore_error (msg_t * message)
{
}
static void
send_error (msg_t * message)
{
if ((THREAD_ERROR_QUEUE ()) == QID_NONE)
OS2_logic_error ("send_error called when no error queue defined.");
OS2_send_message ((THREAD_ERROR_QUEUE ()), message);
longjmp ((THREAD_ERROR_RESTART ()), 1);
}
msg_t *
OS2_make_syscall_error (int code, enum syscall_names name)
{
msg_t * message = (OS2_create_message (mt_syscall_error));
(SM_SYSCALL_ERROR_CODE (message)) = code;
(SM_SYSCALL_ERROR_NAME (message)) = name;
return (message);
}
msg_t *
OS2_make_error (long code)
{
msg_t * message = (OS2_create_message (mt_error));
(SM_ERROR_CODE (message)) = code;
return (message);
}