Add @synchronize support. The synchronize.m file will be committed to GCC as soon as Andrew P. looks at it and it is tested fully. I am committing it here for cases where the compiler can parse @synchronize, but doesn't have the necessary functions in the runtime.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@26869 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Gregory John Casamento 2008-09-24 04:38:27 +00:00
parent 6f85f5292c
commit 3d16dda1a5
7 changed files with 7641 additions and 7033 deletions

View file

@ -1,3 +1,15 @@
2008-09-23 20:31-EDT Gregory John Casamento <greg_casamento@yahoo.com>
* config.mak.in: Added reference to HAVE_OBJC_SYNC_ENTER
* configure: Recompiled script
* configure.ac: Changed configure to check for objc_sync_enter
function.
* Headers/Additions/GNUstepBase/config.h.in: Added #define here for
HAVE_OBJC_SYNC_ENTER
* Source/GNUmakefile: Added check for the value, if no, then compile
synchronization.m
* Source/synchronization.m: Implementation for @synchronize support.
2008-09-23 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSThread.m: add a couple of checks to ensure correct

View file

@ -652,6 +652,10 @@
first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
/* Define to 1 if the libobjc library contains objc_sync_enter and supports
the @synchronize directive. If not, then we'll provide it. */
#undef HAVE_OBJC_SYNC_ENTER
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus

View file

@ -109,6 +109,11 @@ ifeq ($(GNUSTEP_TARGET_OS), mingw32)
GNU_MFILES += libgnustep-base-entry.m
endif
ifeq ($(HAVE_OBJC_SYNC_ENTER), no)
GNU_MFILES += synchronization.m
endif
GNU_OTHER_SRCFILES = \
win32-entry.m \
win32-def.top \

244
Source/synchronization.m Normal file
View file

@ -0,0 +1,244 @@
/*
The implementation of synchronization primitives for Objective-C.
Copyright (C) 2008 Free Software Foundation, Inc.
This file is part of GCC.
Gregory Casamento <greg.casamento@gmail.com>
GCC 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.
GCC 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 GCC; see the file COPYING. If not, write to
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/*
As a special exception, if you link this library with files compiled
with GCC to produce an executable, this does not cause the resulting
executable to be covered by the GNU General Public License. This
exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License.
*/
#include <stdlib.h>
#include "objc/objc.h"
#include "objc/objc-api.h"
#include "objc/thr.h"
/*
* Node structure...
*/
typedef struct lock_node {
id obj;
objc_mutex_t lock;
struct lock_node *next;
struct lock_node *prev;
} lock_node_t;
/*
* Return types for the locks...
*/
typedef enum {
OBJC_SYNC_SUCCESS = 0,
OBJC_SYNC_NOT_OWNING_THREAD_ERROR = -1,
OBJC_SYNC_TIMED_OUT = -2,
OBJC_SYNC_NOT_INITIALIZED = -3
} sync_return_t;
static lock_node_t *lock_list = NULL;
static objc_mutex_t table_lock = NULL;
/**
* Initialize the table lock.
*/
static void sync_lock_init()
{
if(table_lock == NULL)
{
table_lock = objc_mutex_allocate();
}
}
/**
* Find the node in the list.
*/
lock_node_t* objc_sync_find_node(id obj)
{
lock_node_t *current = NULL;
if(lock_list != NULL)
{
// iterate over the list looking for the end...
while(current != NULL)
{
// if the current object is the one, breal and
// return that node.
if(current->obj == obj)
{
break;
}
// get the next one...
current = current->next;
}
}
return current;
}
/**
* Add a node for the object, if one doesn't already exist.
*/
lock_node_t* objc_sync_add_node(id obj)
{
lock_node_t *current = NULL;
// get the lock...
sync_lock_init();
// restrict access to the table....
objc_mutex_lock(table_lock);
// if the list hasn't been initialized, initialize it.
if(lock_list == NULL)
{
// instantiate the new node and set the list...
lock_list = malloc(sizeof(lock_node_t));
// set the current node to the last in the list...
current = lock_list;
// set next and prev...
current->prev = NULL;
current->next = NULL;
}
else
{
lock_node_t *new_node = NULL;
current = lock_list;
// look for the end of the list.
while(current->next)
{
current = current->next;
}
// instantiate the new node...
new_node = malloc(sizeof(lock_node_t));
if(new_node != NULL)
{
// set next and prev...
current->next = new_node;
new_node->prev = current;
new_node->next = NULL;
// set the current node to the last in the list...
current = new_node;
}
}
if(current != NULL)
{
// add the object and it's lock
current->obj = obj;
current->lock = objc_mutex_allocate();
}
// release access to the table...
objc_mutex_unlock(table_lock);
return current;
}
/**
* Remove the node for the object if one does exist.
*/
lock_node_t* objc_sync_remove_node(id obj)
{
lock_node_t *curr = NULL;
// find the node...
curr = objc_sync_find_node(obj);
// if the node is not null, proceed...
if(curr != NULL)
{
// skip the current node in
// the list and remove it from the
// prev and next nodes.
lock_node_t *prev = NULL;
lock_node_t *next = NULL;
prev = curr->prev;
next = curr->next;
next->prev = prev;
prev->next = next;
}
// return the removed node...
return curr;
}
/**
* Add a lock for the object.
*/
int objc_sync_enter(id obj)
{
lock_node_t *node = NULL;
int status = 0;
node = objc_sync_find_node(obj);
if(node == NULL)
{
node = objc_sync_add_node(obj);
if(node == NULL)
{
return OBJC_SYNC_NOT_INITIALIZED;
}
}
status = objc_mutex_lock(node->lock);
if(status < 1)
{
return OBJC_SYNC_NOT_OWNING_THREAD_ERROR;
}
return OBJC_SYNC_SUCCESS;
}
/**
* Remove a lock for the object.
*/
int objc_sync_exit(id obj)
{
lock_node_t *node = NULL;
int status = 0;
node = objc_sync_remove_node(obj);
if(node == NULL)
{
return OBJC_SYNC_NOT_INITIALIZED;
}
status = objc_mutex_unlock(node->lock);
if(status < 1)
{
return OBJC_SYNC_NOT_OWNING_THREAD_ERROR;
}
// dealloc the node and return success.
free(node);
return OBJC_SYNC_SUCCESS;
}

View file

@ -21,6 +21,7 @@ NX_CONST_STRING_CLASS=@NX_CONST_STRING_CLASS@
HAVE_PTHREAD_H=@HAVE_PTHREAD_H@
HAVE_INET_PTON=@HAVE_INET_PTON@
HAVE_INET_NTOP=@HAVE_INET_NTOP@
HAVE_OBJC_SYNC_ENTER=@HAVE_OBJC_SYNC_ENTER@
CONFIG_SYSTEM_INCL += @INCLUDE_FLAGS@
ifeq ($(shared),yes)

14397
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -1309,6 +1309,17 @@ AC_EGREP_HEADER(objc_get_uninstalled_dtable, objc/objc-api.h,
LIBS="$saved_LIBS"
CPPFLAGS="$saved_CPPFLAGS"
#--------------------------------------------------------------------
# Function needed by @synchronize directive
#--------------------------------------------------------------------
AC_CHECK_FUNCS(objc_sync_enter)
HAVE_OBJC_SYNC_ENTER=no
if test $ac_cv_func_objc_sync_enter = yes ; then
HAVE_OBJC_SYNC_ENTER=yes
fi
AC_SUBST(HAVE_OBJC_SYNC_ENTER)
#--------------------------------------------------------------------
# Generic settings needed by NSZone.m
#--------------------------------------------------------------------