From 929ec2412fa97a6c61ed8b32831343dbec243944 Mon Sep 17 00:00:00 2001 From: vsc Date: Wed, 2 Apr 2008 17:37:07 +0000 Subject: [PATCH] handle out of memory error at thread creation (obs from Paulo Moura). git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@2190 b08c6af1-5177-4d33-ba66-4b1c6b8b522a --- C/alloc.c | 7 +++++-- C/c_interface.c | 16 +++++++++++++++- C/threads.c | 36 ++++++++++++++++++++++++++++-------- H/Heap.h | 3 ++- H/Yap.h | 3 ++- pl/messages.yap | 4 +++- pl/threads.yap | 31 +++++++++++++++++++++++++++---- 7 files changed, 82 insertions(+), 18 deletions(-) diff --git a/C/alloc.c b/C/alloc.c index 7b3c6bc5f..6bfdbd8f5 100644 --- a/C/alloc.c +++ b/C/alloc.c @@ -12,7 +12,7 @@ * Last rev: * * mods: * * comments: allocating space * -* version:$Id: alloc.c,v 1.91 2008-04-01 22:28:41 vsc Exp $ * +* version:$Id: alloc.c,v 1.92 2008-04-02 17:37:05 vsc Exp $ * *************************************************************************/ #ifdef SCCS static char SccsId[] = "%W% %G%"; @@ -233,7 +233,10 @@ InitExStacks(int Trail, int Stack) * requested */ sa = Stack*K; /* stack area size */ - Yap_GlobalBase = malloc(pm); +#ifdef THREADS + if (worker_id) + Yap_GlobalBase = (ADDR)ThreadHandle[worker_id].stack_address; +#endif Yap_TrailTop = Yap_GlobalBase + pm; Yap_LocalBase = Yap_GlobalBase + sa; Yap_TrailBase = Yap_LocalBase + sizeof(CELL); diff --git a/C/c_interface.c b/C/c_interface.c index df45fd816..dd6fc6cb0 100644 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -10,8 +10,11 @@ * File: c_interface.c * * comments: c_interface primitives definition * * * -* Last rev: $Date: 2008-04-01 15:31:41 $,$Author: vsc $ * +* Last rev: $Date: 2008-04-02 17:37:06 $,$Author: vsc $ * * $Log: not supported by cvs2svn $ +* Revision 1.109 2008/04/01 15:31:41 vsc +* more saved state fixes +* * Revision 1.108 2008/03/22 23:35:00 vsc * fix bug in all_calls * @@ -1689,6 +1692,17 @@ YAP_Init(YAP_init_args *yap_init) yap_init->SchedulerLoop, yap_init->DelayedReleaseLoad ); +#if USE_SYSTEM_MALLOC + if (Trail < MinTrailSpace) + Trail = MinTrailSpace; + if (Stack < MinStackSpace) + Stack = MinStackSpace; + if (!(Yap_GlobalBase = (ADDR)malloc((Trail+Stack)*1024))) { + yap_init->ErrorNo = RESOURCE_ERROR_MEMORY; + yap_init->ErrorCause = "could not allocate stack space for main thread"; + return YAP_BOOT_FROM_SAVED_ERROR;; + } +#endif Yap_InitExStacks (Trail, Stack); if (yap_init->QuietMode) { yap_flags[QUIET_MODE_FLAG] = TRUE; diff --git a/C/threads.c b/C/threads.c index f3a9580ed..ae14e7ec5 100644 --- a/C/threads.c +++ b/C/threads.c @@ -57,11 +57,20 @@ allocate_new_tid(void) return new_worker_id; } -static void +static int store_specs(int new_worker_id, UInt ssize, UInt tsize, Term tgoal, Term tdetach) { + UInt pm; /* memory to be requested */ + if (tsize < MinTrailSpace) + tsize = MinTrailSpace; + if (ssize < MinStackSpace) + ssize = MinStackSpace; ThreadHandle[new_worker_id].ssize = ssize; ThreadHandle[new_worker_id].tsize = tsize; + pm = (ssize + tsize)*1024; + if (!(ThreadHandle[new_worker_id].stack_address = malloc(pm))) { + return FALSE; + } ThreadHandle[new_worker_id].tgoal = Yap_StoreTermInDB(tgoal,4); ThreadHandle[new_worker_id].cmod = @@ -73,6 +82,7 @@ store_specs(int new_worker_id, UInt ssize, UInt tsize, Term tgoal, Term tdetach) ThreadHandle[new_worker_id].tdetach = tdetach; } + return TRUE; } @@ -190,27 +200,36 @@ p_thread_new_tid(void) return Yap_unify(MkIntegerTerm(new_worker), ARG1); } -static void +static int init_thread_engine(int new_worker_id, UInt ssize, UInt tsize, Term tgoal, Term tdetach) { - store_specs(new_worker_id, ssize, tsize, tgoal, tdetach); + return store_specs(new_worker_id, ssize, tsize, tgoal, tdetach); } static Int p_create_thread(void) { - UInt ssize = IntegerOfTerm(Deref(ARG2)); - UInt tsize = IntegerOfTerm(Deref(ARG3)); - /* UInt systemsize = IntegerOfTerm(Deref(ARG4)); */ + UInt ssize; + UInt tsize; Term tgoal = Deref(ARG1); Term tdetach = Deref(ARG5); + Term x2 = Deref(ARG2); + Term x3 = Deref(ARG3); int new_worker_id = IntegerOfTerm(Deref(ARG6)); + if (IsBigIntTerm(x2)) + return FALSE; + if (IsBigIntTerm(x3)) + return FALSE; + ssize = IntegerOfTerm(x2); + tsize = IntegerOfTerm(x3); + /* UInt systemsize = IntegerOfTerm(Deref(ARG4)); */ if (new_worker_id == -1) { /* YAP ERROR */ return FALSE; } - init_thread_engine(new_worker_id, ssize, tsize, tgoal, tdetach); + if (!init_thread_engine(new_worker_id, ssize, tsize, tgoal, tdetach)) + return FALSE; ThreadHandle[new_worker_id].id = new_worker_id; ThreadHandle[new_worker_id].ref_count = 1; if ((ThreadHandle[new_worker_id].ret = pthread_create(&ThreadHandle[new_worker_id].handle, NULL, thread_run, (void *)(&(ThreadHandle[new_worker_id].id)))) == 0) { @@ -298,7 +317,8 @@ Yap_thread_create_engine(thread_attr *ops) /* YAP ERROR */ return FALSE; } - init_thread_engine(new_id, ops->ssize, ops->tsize, TermNil, TermNil); + if (!init_thread_engine(new_id, ops->ssize, ops->tsize, TermNil, TermNil)) + return FALSE; ThreadHandle[new_id].id = new_id; ThreadHandle[new_id].handle = pthread_self(); ThreadHandle[new_id].ref_count = 0; diff --git a/H/Heap.h b/H/Heap.h index 4e6dd9cca..39c8ead82 100644 --- a/H/Heap.h +++ b/H/Heap.h @@ -10,7 +10,7 @@ * File: Heap.h * * mods: * * comments: Heap Init Structure * -* version: $Id: Heap.h,v 1.129 2008-04-02 15:41:50 vsc Exp $ * +* version: $Id: Heap.h,v 1.130 2008-04-02 17:37:06 vsc Exp $ * *************************************************************************/ /* information that can be stored in Code Space */ @@ -185,6 +185,7 @@ typedef struct thandle { int zombie; UInt ssize; UInt tsize; + void *stack_address; Term tdetach; Term cmod; struct DB_TERM *tgoal; diff --git a/H/Yap.h b/H/Yap.h index 6730760fa..da44aa489 100644 --- a/H/Yap.h +++ b/H/Yap.h @@ -10,7 +10,7 @@ * File: Yap.h.m4 * * mods: * * comments: main header file for YAP * -* version: $Id: Yap.h,v 1.32 2008-04-02 15:41:50 vsc Exp $ * +* version: $Id: Yap.h,v 1.33 2008-04-02 17:37:06 vsc Exp $ * *************************************************************************/ #include "config.h" @@ -479,6 +479,7 @@ typedef enum REPRESENTATION_ERROR_CHARACTER_CODE, REPRESENTATION_ERROR_MAX_ARITY, RESOURCE_ERROR_MAX_THREADS, + RESOURCE_ERROR_MEMORY, RETRY_COUNTER_UNDERFLOW, SYNTAX_ERROR, SYSTEM_ERROR, diff --git a/pl/messages.yap b/pl/messages.yap index b6b540c7f..fcfff1ee4 100644 --- a/pl/messages.yap +++ b/pl/messages.yap @@ -11,7 +11,7 @@ * File: utilities for displaying messages in YAP. * * comments: error messages for YAP * * * -* Last rev: $Date: 2008-03-27 00:41:33 $,$Author: vsc $ * +* Last rev: $Date: 2008-04-02 17:37:07 $,$Author: vsc $ * * * * * *************************************************************************/ @@ -241,6 +241,8 @@ system_message(error(representation_error(max_arity), Where)) --> [ 'REPRESENTATION ERROR- ~w: number too big' - [Where] ]. system_message(error(resource_error(threads), Where)) --> [ 'RESOURCE ERROR- too many open threads' - [Where] ]. +system_message(error(resource_error(memory), Where)) --> + [ 'RESOURCE ERROR- not enough virtual memory' - [Where] ]. system_message(error(syntax_error(G,0,Msg,[],0,0), _)) --> [ 'SYNTAX ERROR: ~a' - [G,Msg] ]. system_message(error(syntax_error(_,_,_,Term,Pos,Start), Where)) --> diff --git a/pl/threads.yap b/pl/threads.yap index 0eea953f7..41a9a06e5 100644 --- a/pl/threads.yap +++ b/pl/threads.yap @@ -63,7 +63,12 @@ '$run_at_thread_exit'(Id0), ( Detached == true -> '$erase_thread_info'(Id0) - ; recorda('$thread_exit_status', [Id0|exception(Exception)], _) + ; + ( + recorded('$thread_exit_status',[Id|_],R), erase(R), fail + ; + recorda('$thread_exit_status', [Id|exception(error(resource_error(memory),thread_create(Goal,Id)))]) + ) ). thread_create(Goal) :- @@ -74,7 +79,13 @@ thread_create(Goal) :- '$erase_thread_info'(Id), '$record_thread_info'(Id, [Stack, Trail, System], Detached, AtExit), '$create_thread_mq'(Id), - '$create_thread'(Goal, Stack, Trail, System, Detached, Id). + ( + '$create_thread'(Goal, Stack, Trail, System, Detached, Id) + -> + true + ; + recorda('$thread_exit_status', [Id|exception(error(resource_error(memory),thread_create(Goal,Id)))],_) + ). thread_create(Goal, OutId) :- G0 = thread_create(Goal, Id), @@ -85,7 +96,13 @@ thread_create(Goal, OutId) :- '$erase_thread_info'(Id), '$record_thread_info'(Id, [Stack, Trail, System], Detached, AtExit), '$create_thread_mq'(Id), - '$create_thread'(Goal, Stack, Trail, System, Detached, Id), + ( + '$create_thread'(Goal, Stack, Trail, System, Detached, Id) + -> + true + ; + recorda('$thread_exit_status', [Id|exception(error(resource_error(memory),thread_create(Goal,Id)))],_) + ), OutId = Id. thread_create(Goal, OutId, Options) :- @@ -100,7 +117,13 @@ thread_create(Goal, OutId, Options) :- ; '$record_thread_info'(Id, Alias, [Stack, Trail, System], Detached, AtExit, G0) ), '$create_thread_mq'(Id), - '$create_thread'(Goal, Stack, Trail, System, Detached, Id), + ( + '$create_thread'(Goal, Stack, Trail, System, Detached, Id) + -> + true + ; + recorda('$thread_exit_status', [Id|exception(error(resource_error(memory),thread_create(Goal,Id,Options)))],_) + ), OutId = Id. '$erase_thread_info'(Id) :-