[Mono-list] mono, porting to non glibc systems, and pthread mutex
implementations...
Jeffrey Stedfast
fejj@ximian.com
12 Feb 2002 23:18:07 -0500
--=-4U/rJEmVv+DoQ5FXGDhy
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
This weekend I began porting the mono interpreter to SPARC systems
although lupus@ximian.com apparently had the same idea and beat me to
the punch ;-)
Since Paolo didn't have access to a sparc, Miguel has asked me to test
the code and to finish porting if necessary. This also means porting
other code to SunOS/Solaris.
Unfortunately, SunOS 5.8 seems to not support the
PTHREAD_MUTEX_RECURSIVE attribute, nor does it seem to support
pthread_mutexattr_settype(). Reading my manpages on my Linux system also
show these as unsupported/non-portable (there was no
PTHREAD_MUTEX_RECUSIVE but there was a PTHREAD_MUTEX_RECURSIVE_NP and
there wasn't a pthread_mutexattr_settype() either) but a quick read in
pthread.h shows that these are enabled for UNIX98 systems.
To solve this problem, I have written a direct wrapper around
pthread_mutex_*() and pthread_mutexattr_*() functions that implement
recursive mutex locking for systems that don't support this natively
(see attached files).
Do begin using my wrapper, simply:
sed -e "s/pthread_mutex/mono_mutex/g" -e "s/PTHREAD_MUTEX/MONO_MUTEX"
(well, for the most part that will work unless we later decide to set
process-sharing attributes or other attributes other than the mutex
types - in which case you'll have to s/PTHREAD/MONO_THREAD/g)
I've also noticed that a function named pthread_mutex_timedlock() is
being used. What does this function do? I can't find it in any
documentation I have on pthreads...
I've noticed that configure.in will AC_WARN() if it's not there and that
there is a #define specifying whether or not it is available but I did
not see checks around the code that uses pthread_mutex_timedlock().
Perhaps I missed something...
Anyways, if someone would like to enlighten me as to what it does,
perhaps I can hack mono_mutex_t to support that operation...
Also: where should these files go? any preferences or shall I dump them
in mono/metadata/?
Jeff
--
Jeffrey Stedfast
Evolution Hacker - Ximian, Inc.
fejj@ximian.com - www.ximian.com
--=-4U/rJEmVv+DoQ5FXGDhy
Content-Disposition: attachment; filename=mono-mutex.h
Content-Transfer-Encoding: quoted-printable
Content-Type: text/x-c-header; charset=ISO-8859-1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Authors: Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 2002 Ximain, Inc. (www.ximian.com)
*
* 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __MONO_MUTEX_H__
#define __MONO_MUTEX_H__
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#include <pthread.h>
#ifdef USE_MONO_MUTEX
#define MONO_THREAD_NONE ((pthread_t)~0)
/* mutex types... */
enum {
MONO_MUTEX_NORMAL,
MONO_MUTEX_RECURSIVE,
MONO_MUTEX_ERRORCHECK =3D MONO_MUTEX_NORMAL,
MONO_MUTEX_DEFAULT =3D MONO_MUTEX_NORMAL
};
/* mutex protocol attributes... */
enum {
MONO_THREAD_PRIO_NONE,
MONO_THREAD_PRIO_INHERIT,
MONO_THREAD_PRIO_PROTECT,
};
/* mutex process sharing attributes... */
enum {
MONO_THREAD_PROCESS_PRIVATE,
MONO_THREAD_PROCESS_SHARED
};
typedef struct _mono_mutexattr_t {
int type : 1;
int shared : 1;
int protocol : 2;
int priority : 28;
} mono_mutexattr_t;
typedef struct _mono_mutex_t {
int type;
pthread_t owner;
short waiters;
short depth;
pthread_mutex_t mutex;
pthread_cond_t cond;
} mono_mutex_t;
/* static initializers */
#define MONO_MUTEX_INITIALIZER { 0, MONO_THREAD_NONE, 0, 0, PTHREAD_MUTEX_I=
NITIALIZER, 0 }
#define MONO_RECURSIVE_MUTEX_INITIALIZER { 0, MONO_THREAD_NONE, 0, 0, PTHRE=
AD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER }
int mono_mutexattr_init (mono_mutexattr_t *attr);
int mono_mutexattr_settype (mono_mutexattr_t *attr, int type);
int mono_mutexattr_gettype (mono_mutexattr_t *attr, int *type);
int mono_mutexattr_setpshared (mono_mutexattr_t *attr, int pshared);
int mono_mutexattr_getpshared (mono_mutexattr_t *attr, int *pshared);
int mono_mutexattr_setprotocol (mono_mutexattr_t *attr, int protocol);
int mono_mutexattr_getprotocol (mono_mutexattr_t *attr, int *protocol);
int mono_mutexattr_setprioceiling (mono_mutexattr_t *attr, int prioceiling)=
;
int mono_mutexattr_getprioceiling (mono_mutexattr_t *attr, int *prioceiling=
);
int mono_mutexattr_destroy (mono_mutexattr_t *attr);
int mono_mutex_init (mono_mutex_t *mutex, const mono_mutexattr_t *attr);
int mono_mutex_lock (mono_mutex_t *mutex);
int mono_mutex_trylock (mono_mutex_t *mutex);
int mono_mutex_unlock (mono_mutex_t *mutex);
int mono_mutex_destroy (mono_mutex_t *mutex);
#else /* system is equipped with a fully-functional pthread mutex library *=
/
#define MONO_MUTEX_NORMAL PTHREAD_MUTEX_NORMAL
#define MONO_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE
#define MONO_MUTEX_ERRORCHECK PTHREAD_MUTEX_NORMAL
#define MONO_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
#define MONO_THREAD_PRIO_NONE PTHREAD_PRIO_NONE
#define MONO_THREAD_PRIO_INHERIT PTHREAD_PRIO_INHERIT
#define MONO_THREAD_PRIO_PROTECT PTHREAD_PRIO_PROTECT
#define MONO_THREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE
#define MONO_THREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED
typedef pthread_mutex_t mono_mutex_t;
typedef pthread_mutexattr_t mono_mutexattr_t;
#define MONO_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define MONO_RECURSIVE_MUTEX_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZE=
R
#define mono_mutexattr_init(attr) pthread_mutexattr_init (attr)
#define mono_mutexattr_settype(attr,type) pthread_mutexattr_settype (attr, =
type)
#define mono_mutexattr_gettype(attr,type) pthread_mutexattr_gettype (attr, =
type)
#define mono_mutexattr_setpshared(attr,pshared) pthread_mutexattr_setpshare=
d (attr, pshared)
#define mono_mutexattr_getpshared(attr,pshared) pthread_mutexattr_getpshare=
d (attr, pshared)
#define mono_mutexattr_setprotocol(attr,protocol) pthread_mutexattr_setprot=
ocol (attr, protocol)
#define mono_mutexattr_getprotocol(attr,protocol) pthread_mutexattr_getprot=
ocol (attr, protocol)
#define mono_mutexattr_setprioceiling(attr,prioceiling) pthread_mutexattr_s=
etprioceiling (attr, prioceiling)
#define mono_mutexattr_getprioceiling(attr,prioceiling) pthread_mutexattr_g=
etprioceiling (attr, prioceiling)
#define mono_mutex_init(mutex,attr) pthread_mutex_init (mutex, attr)
#define mono_mutex_lock(mutex) pthread_mutex_lock (mutex)
#define mono_mutex_trylock(mutex) pthread_mutex_trylock (mutex)
#define mono_mutex_unlock(mutex) pthread_mutex_unlock (mutex)
#define mono_mutex_destroy(mutex) pthread_mutex_destroy (mutex)
#endif /* USE_MONO_MUTEX */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MONO_MUTEX_H__ */
--=-4U/rJEmVv+DoQ5FXGDhy
Content-Disposition: attachment; filename=mono-mutex.c
Content-Transfer-Encoding: quoted-printable
Content-Type: text/x-c; charset=ISO-8859-1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Authors: Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 2002 Ximain, Inc. (www.ximian.com)
*
* 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mono-mutex.h"
#ifdef USE_MONO_MUTEX
int
mono_mutexattr_init (mono_mutexattr_t *attr)
{
memset (attr, 0, sizeof (mono_mutexattr_t));
return 0;
}
int
mono_mutexattr_settype (mono_mutexattr_t *attr, int type)
{
attr->type =3D type;
return 0;
}
int
mono_mutexattr_gettype (mono_mutexattr_t *attr, int *type)
{
*type =3D attr->type;
return 0;
}
int
mono_mutexattr_setpshared (mono_mutexattr_t *attr, int pshared)
{
attr->pshared =3D pshared;
return 0;
}
int
mono_mutexattr_getpshared (mono_mutexattr_t *attr, int *pshared)
{
*pshared =3D attr->pshared;
return 0;
}
int
mono_mutexattr_setprotocol (mono_mutexattr_t *attr, int protocol)
{
attr->protocol =3D protocol;
return 0;
}
int
mono_mutexattr_getprotocol (mono_mutexattr_t *attr, int *protocol)
{
*protocol =3D attr->protocol;
return 0;
}
int
mono_mutexattr_setprioceiling (mono_mutexattr_t *attr, int prioceiling)
{
attr->prioceiling =3D prioceiling;
return 0;
}
int
mono_mutexattr_getprioceiling (mono_mutexattr_t *attr, int *prioceiling)
{
*prioceiling =3D attr->prioceiling;
return 0;
}
int
mono_mutexattr_destroy (mono_mutexattr_t *attr)
{
g_free (attr);
return 0;
}
int
mono_mutex_init (mono_mutex_t *mutex, const mono_mutexattr_t *attr)
{
mutex->waiters =3D 0;
mutex->depth =3D 0;
mutex->owner =3D MONO_THREAD_NONE;
=09
if (!attr || attr->type =3D=3D MONO_MUTEX_NORMAL) {
mutex->type =3D MONO_MUTEX_NORMAL;
pthread_mutex_init (&mutex->mutex, NULL);
} else {
mutex->type =3D MONO_MUTEX_RECURSIVE;
pthread_mutex_init (&mutex->mutex, NULL);
pthread_cond_init (&mutex->cond, NULL);
}
=09
return 0;
}
int
mono_mutex_lock (mono_mutex_t *mutex)
{
pthread_t id;
=09
switch (mutex->type) {
case MONO_MUTEX_NORMAL:
return pthread_mutex_lock (&mutex->mutex);
case MONO_MUTEX_RECURSIVE:
id =3D pthread_self ();
if (pthread_mutex_lock (&mutex->mutex) =3D=3D -1)
return -1;
while (1) {
if (mutex->owner =3D=3D MONO_THREAD_NONE) {
mutex->owner =3D id;
mutex->depth =3D 1;
break;
} else if (id =3D=3D mutex->owner) {
mutex->depth++;
break;
} else {
mutex->waiters++;
if (pthread_cond_wait (&mutex->cond, &mutex->mutex) =3D=3D -1)
return -1;
mutex->waiters--;
}
}
=09
return pthread_mutex_unlock (&mutex->mutex);
}
=09
errno =3D EINVAL;
=09
return -1;
}
int
mono_mutex_trylock (mono_mutex_t *mutex)
{
switch (mutex->type) {
case MONO_MUTEX_NORMAL:
return pthread_mutex_trylock (&mutex->mutex);
case MONO_MUTEX_RECURSIVE:
if (pthread_mutex_lock (&mutex->mutex) =3D=3D -1)
return -1;
=09
if (mutex->id !=3D MONO_THREAD_NONE && mutex->id !=3D pthread_self ()) {
pthread_mutex_unlock (&mutex->mutex);
errno =3D EBUSY;
return -1;
}
=09
while (1) {
if (mutex->owner =3D=3D MONO_THREAD_NONE) {
mutex->owner =3D id;
mutex->depth =3D 1;
break;
} else if (id =3D=3D mutex->owner) {
mutex->depth++;
break;
} else {
mutex->waiters++;
if (pthread_cond_wait (&mutex->cond, &mutex->mutex) =3D=3D -1)
return -1;
mutex->waiters--;
}
}
=09
return pthread_mutex_unlock (&mutex->mutex);
}
}
int
mono_mutex_unlock (mono_mutex_t *mutex)
{
switch (mutex->type) {
case MONO_MUTEX_NORMAL:
return pthread_mutex_unlock (&mutex->mutex);
case MONO_MUTEX_RECURSIVE:
if (pthread_mutex_lock (&mutex->mutex) =3D=3D -1)
return -1;
=09
g_assert (mutex->owner =3D=3D pthread_self ());
=09
mutex->depth--;
if (mutex->depth =3D=3D 0) {
mutex->owner =3D MONO_THREAD_NONE;
if (mutex->waiters > 0)
pthread_cond_signal (&mutex->cond);
}
=09
return pthread_mutex_unlock (&mutex->mutex);
}
=09
errno =3D EINVAL;
=09
return -1;
}
int
mono_mutex_destroy (mono_mutex_t *mutex)
{
int ret =3D 0;
=09
switch (mutex->type) {
case MONO_MUTEX_NORMAL:
ret =3D pthread_mutex_destroy (&mutex->mutex);
g_free (mutex);
break;
case MONO_MUTEX_RECURSIVE:
ret =3D pthread_mutex_destroy (&mutex->mutex);
ret =3D pthread_cond_destroy (&mutex->cond);
g_free (mutex);
}
=09
return ret;
}
#endif /* USE_MONO_MUTEX */
--=-4U/rJEmVv+DoQ5FXGDhy--