forked from 0ad/0ad
add sem_msgwait_np for philip/use with atlas. add API fail reporting for sem_*
networkInternal - remove E* error codes; rely on system <errno.h> header wposix: add all SUSv3 error codes; value = that of CRT (where available), otherwise the linux value This was SVN commit r3087.
This commit is contained in:
parent
7bfe647366
commit
668794e61d
@ -67,65 +67,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// <errno.h>
|
||||
//
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
// not defined there:
|
||||
#define EINPROGRESS 100000
|
||||
#define ETIMEDOUT (60) // matches NetworkInternal.h def
|
||||
|
||||
/*
|
||||
enum
|
||||
{
|
||||
EINPROGRESS = 1000, // Operation in progress.
|
||||
ENOMEM // Not enough space.
|
||||
EACCES, // Permission denied.
|
||||
EADDRINUSE, // Address in use.
|
||||
EADDRNOTAVAIL, // Address not available.
|
||||
EAGAIN, // Resource unavailable, try again (may be the same value as EWOULDBLOCK]).
|
||||
EALREADY, // Connection already in progress.
|
||||
EBADF, // Bad file descriptor.
|
||||
ECANCELED, // Operation canceled.
|
||||
ECONNABORTED, // Connection aborted.
|
||||
ECONNREFUSED, // Connection refused.
|
||||
ECONNRESET, // Connection reset.
|
||||
EDOM, // Mathematics argument out of domain of function.
|
||||
EEXIST, // File exists.
|
||||
EFAULT, // Bad address.
|
||||
EHOSTUNREACH, // Host is unreachable.
|
||||
EINTR, // Interrupted function.
|
||||
EINVAL, // Invalid argument.
|
||||
EISCONN, // Socket is connected.
|
||||
EISDIR, // Is a directory.
|
||||
ENAMETOOLONG, // Filename too long.
|
||||
ENETDOWN, // Network is down.
|
||||
ENETRESET, // Connection aborted by network.
|
||||
ENETUNREACH, // Network unreachable.
|
||||
ENOENT, // No such file or directory.
|
||||
ENOEXEC, // Executable file format error.
|
||||
|
||||
ENOSPC, // No space left on device.
|
||||
ENOSYS, // Function not supported.
|
||||
ENOTCONN, // The socket is not connected.
|
||||
ENOTDIR, // Not a directory.
|
||||
ENOTEMPTY, // Directory not empty.
|
||||
ENOTSOCK, // Not a socket.
|
||||
ENOTSUP, // Not supported.
|
||||
EOVERFLOW, // Value too large to be stored in data type.
|
||||
EPERM, // Operation not permitted.
|
||||
EPIPE, // Broken pipe.
|
||||
EPROTO, // Protocol error.
|
||||
ERANGE, // Result too large.
|
||||
ETIMEDOUT, // Connection timed out.
|
||||
EWOULDBLOCK // Operation would block (may be the same value as EAGAIN]).
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// sys/stat.h
|
||||
//
|
||||
@ -375,6 +316,97 @@ struct utsname
|
||||
extern int uname(struct utsname*);
|
||||
|
||||
|
||||
//
|
||||
// <errno.h>
|
||||
//
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
// this is an exhaustive list of SUSv3 error codes;
|
||||
// see http://www.opengroup.org/onlinepubs/009695399/basedefs/errno.h.html .
|
||||
// .. the following are already correctly defined by VC errno.h:
|
||||
#if 0
|
||||
#define EPERM 1 // Operation not permitted
|
||||
#define ENOENT 2 // No such file or directory
|
||||
#define ESRCH 3 // No such process
|
||||
#define EINTR 4 // Interrupted system call
|
||||
#define EIO 5 // I/O error
|
||||
#define ENXIO 6 // No such device or address
|
||||
#define E2BIG 7 // Argument list too long
|
||||
#define ENOEXEC 8 // Exec format error
|
||||
#define EBADF 9 // Bad file number
|
||||
#define ECHILD 10 // No child processes
|
||||
#define EAGAIN 11 // Try again
|
||||
#define ENOMEM 12 // Out of memory
|
||||
#define EACCES 13 // Permission denied
|
||||
#define EFAULT 14 // Bad address
|
||||
#define EBUSY 16 // Device or resource busy
|
||||
#define EEXIST 17 // File exists
|
||||
#define ENODEV 19 // No such device
|
||||
#define ENOTDIR 20 // Not a directory
|
||||
#define EISDIR 21 // Is a directory
|
||||
#define EINVAL 22 // Invalid argument
|
||||
#define ENFILE 23 // File table overflow
|
||||
#define EMFILE 24 // Too many open files
|
||||
#define ENOTTY 25 // Not a typewriter
|
||||
#define EFBIG 27 // File too large
|
||||
#define ENOSPC 28 // No space left on device
|
||||
#define ESPIPE 29 // Illegal seek
|
||||
#define EMLINK 31 // Too many links
|
||||
#define EPIPE 32 // Broken pipe
|
||||
#define EDOM 33 // Math argument out of domain of func
|
||||
#define ERANGE 34 // Math result not representable
|
||||
#endif
|
||||
// .. the following are unfortunately defined differently by VC errno.h;
|
||||
// we have to stick with those interpretations because they are set
|
||||
// by already-compiled CRT code.
|
||||
#if 0
|
||||
#define EDEADLK 35 // Resource deadlock would occur
|
||||
#define ENAMETOOLONG 36 // File name too long
|
||||
#define ENOLCK 37 // No record locks available
|
||||
#define ENOSYS 38 // Function not implemented
|
||||
#define ENOTEMPTY 39 // Directory not empty
|
||||
#define EILSEQ 84 // Illegal byte sequence
|
||||
#endif
|
||||
// .. the following aren't yet defined; we take on the Linux values for
|
||||
// simplicity (why assign different values?)
|
||||
#define ELOOP 40 // Too many symbolic links encountered
|
||||
#define ENOMSG 42 // No message of desired type
|
||||
#define EIDRM 43 // Identifier removed
|
||||
#define EWOULDBLOCK EAGAIN // Operation would block
|
||||
#define ENOLINK 67 // Reserved
|
||||
#define EPROTO 71 // Protocol error
|
||||
#define EMULTIHOP 72 // Reserved
|
||||
#define EBADMSG 74 // Not a data message
|
||||
#define EOVERFLOW 75 // Value too large for defined data type
|
||||
#define ENOTSOCK 88 // Socket operation on non-socket
|
||||
#define EDESTADDRREQ 89 // Destination address required
|
||||
#define EMSGSIZE 90 // Message too long
|
||||
#define EPROTOTYPE 91 // Protocol wrong type for socket
|
||||
#define ENOPROTOOPT 92 // Protocol not available
|
||||
#define EPROTONOSUPPORT 93 // Protocol not supported
|
||||
#define EOPNOTSUPP 95 // Operation not supported on transport endpoint
|
||||
#define EAFNOSUPPORT 97 // Address family not supported by protocol
|
||||
#define EADDRINUSE 98 // Address already in use
|
||||
#define EADDRNOTAVAIL 99 // Cannot assign requested address
|
||||
#define ENETDOWN 100 // Network is down
|
||||
#define ENETUNREACH 101 // Network is unreachable
|
||||
#define ENETRESET 102 // Network dropped connection because of reset
|
||||
#define ECONNABORTED 103 // Software caused connection abort
|
||||
#define ECONNRESET 104 // Connection reset by peer
|
||||
#define ENOBUFS 105 // No buffer space available
|
||||
#define EISCONN 106 // Transport endpoint is already connected
|
||||
#define ENOTCONN 107 // Transport endpoint is not connected
|
||||
#define ETIMEDOUT 110 // Connection timed out
|
||||
#define ECONNREFUSED 111 // Connection refused
|
||||
#define EHOSTUNREACH 113 // No route to host
|
||||
#define EALREADY 114 // Operation already in progress
|
||||
#define EINPROGRESS 115 // Operation now in progress
|
||||
#define ESTALE 116 // Reserved
|
||||
#define EDQUOT 122 // Reserved
|
||||
#define ECANCELED 125 // Operation Canceled
|
||||
|
||||
|
||||
//
|
||||
// serial port IOCTL
|
||||
//
|
||||
|
@ -402,7 +402,7 @@ int pthread_mutex_timedlock(pthread_mutex_t* UNUSED(m), const struct timespec* U
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
HANDLE sem_t_to_HANDLE(sem_t* sem)
|
||||
static HANDLE HANDLE_from_sem_t(sem_t* sem)
|
||||
{
|
||||
return (HANDLE)*sem;
|
||||
}
|
||||
@ -411,28 +411,32 @@ int sem_init(sem_t* sem, int pshared, unsigned value)
|
||||
{
|
||||
SECURITY_ATTRIBUTES sec = { sizeof(SECURITY_ATTRIBUTES) };
|
||||
sec.bInheritHandle = (BOOL)pshared;
|
||||
*sem = (uintptr_t)CreateSemaphore(&sec, (LONG)value, 0x7fffffff, 0);
|
||||
HANDLE h = CreateSemaphore(&sec, (LONG)value, 0x7fffffff, 0);
|
||||
WARN_IF_FALSE(h);
|
||||
*sem = (uintptr_t)h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_post(sem_t* sem)
|
||||
{
|
||||
HANDLE h = sem_t_to_HANDLE(sem);
|
||||
ReleaseSemaphore(h, 1, 0);
|
||||
HANDLE h = HANDLE_from_sem_t(sem);
|
||||
WARN_IF_FALSE(ReleaseSemaphore(h, 1, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_wait(sem_t* sem)
|
||||
{
|
||||
HANDLE h = sem_t_to_HANDLE(sem);
|
||||
WaitForSingleObject(h, INFINITE);
|
||||
HANDLE h = HANDLE_from_sem_t(sem);
|
||||
DWORD ret = WaitForSingleObject(h, INFINITE);
|
||||
if(ret != WAIT_OBJECT_0)
|
||||
debug_warn("unexpected WaitForSingleObject return value");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_destroy(sem_t* sem)
|
||||
{
|
||||
HANDLE h = sem_t_to_HANDLE(sem);
|
||||
CloseHandle(h);
|
||||
HANDLE h = HANDLE_from_sem_t(sem);
|
||||
WARN_IF_FALSE(CloseHandle(h));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -485,7 +489,7 @@ int sem_timedwait(sem_t* sem, const struct timespec* abs_timeout)
|
||||
bool timeout_is_valid;
|
||||
DWORD timeout_ms = calc_timeout_length_ms(abs_timeout, timeout_is_valid);
|
||||
|
||||
HANDLE h = sem_t_to_HANDLE(sem);
|
||||
HANDLE h = HANDLE_from_sem_t(sem);
|
||||
DWORD ret = WaitForSingleObject(h, timeout_ms);
|
||||
// successfully decremented semaphore; bail.
|
||||
if(ret == WAIT_OBJECT_0)
|
||||
@ -501,3 +505,40 @@ int sem_timedwait(sem_t* sem, const struct timespec* abs_timeout)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// wait until semaphore is locked or a message arrives. non-portable.
|
||||
//
|
||||
// background: on Win32, UI threads must periodically pump messages, or
|
||||
// else deadlock may result (see WaitForSingleObject docs). that entails
|
||||
// avoiding any blocking functions. when event waiting is needed,
|
||||
// one cheap workaround would be to time out periodically and pump messages.
|
||||
// that would work, but either wastes CPU time waiting, or introduces
|
||||
// message latency. to avoid this, we provide an API similar to sem_wait and
|
||||
// sem_timedwait that gives MsgWaitForMultipleObjects functionality.
|
||||
//
|
||||
// return value: 0 if the semaphore has been locked (SUS terminology),
|
||||
// -1 otherwise. errno differentiates what happened: ETIMEDOUT if a
|
||||
// message arrived (this is to ease switching between message waiting and
|
||||
// periodic timeout), or an error indication.
|
||||
int sem_msgwait_np(sem_t* sem)
|
||||
{
|
||||
HANDLE h = HANDLE_from_sem_t(sem);
|
||||
DWORD ret = MsgWaitForMultipleObjects(1, &h, FALSE, INFINITE, QS_ALLEVENTS);
|
||||
// semaphore is signalled
|
||||
if(ret == WAIT_OBJECT_0)
|
||||
return 0;
|
||||
|
||||
// something else:
|
||||
// .. message came up
|
||||
if(ret == WAIT_OBJECT_0+1)
|
||||
errno = ETIMEDOUT;
|
||||
// .. error
|
||||
else
|
||||
{
|
||||
errno = EINVAL;
|
||||
debug_warn("unexpected MsgWaitForMultipleObjects return value");
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
@ -99,4 +99,20 @@ extern int sem_wait(sem_t*);
|
||||
extern int sem_timedwait(sem_t*, const struct timespec*);
|
||||
extern int sem_destroy(sem_t*);
|
||||
|
||||
// wait until semaphore is locked or a message arrives. non-portable.
|
||||
//
|
||||
// background: on Win32, UI threads must periodically pump messages, or
|
||||
// else deadlock may result (see WaitForSingleObject docs). that entails
|
||||
// avoiding any blocking functions. when event waiting is needed,
|
||||
// one cheap workaround would be to time out periodically and pump messages.
|
||||
// that would work, but either wastes CPU time waiting, or introduces
|
||||
// message latency. to avoid this, we provide an API similar to sem_wait and
|
||||
// sem_timedwait that gives MsgWaitForMultipleObjects functionality.
|
||||
//
|
||||
// return value: 0 if the semaphore has been locked (SUS terminology),
|
||||
// -1 otherwise. errno differentiates what happened: ETIMEDOUT if a
|
||||
// message arrived (this is to ease switching between message waiting and
|
||||
// periodic timeout), or an error indication.
|
||||
extern int sem_msgwait_np(sem_t* sem);
|
||||
|
||||
#endif // #ifndef WPTHREAD_H__
|
||||
|
@ -20,21 +20,6 @@
|
||||
// i.e. the same error name can be used in winsock and posix
|
||||
#define WSABASEERR 10000
|
||||
|
||||
#define EWOULDBLOCK (35)
|
||||
#define ENETDOWN (50)
|
||||
#define ENETUNREACH (51)
|
||||
#define ENETRESET (52)
|
||||
#define ENOTCONN (57)
|
||||
#define ESHUTDOWN (58)
|
||||
#define ENOTCONN (57)
|
||||
#define ECONNABORTED (53)
|
||||
#define ECONNRESET (54)
|
||||
#define ETIMEDOUT (60)
|
||||
#define EADDRINUSE (48)
|
||||
#define EADDRNOTAVAIL (49)
|
||||
#define ECONNREFUSED (61)
|
||||
#define EHOSTUNREACH (65)
|
||||
|
||||
#define MSG_SOCKET_READY WM_USER
|
||||
|
||||
#endif // #if OS_WIN
|
||||
|
Loading…
Reference in New Issue
Block a user