001 /*----------------------------------------------------------------------------*/ 002 /* Copyright (c) FIRST 2008-2012. All Rights Reserved. */ 003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 004 /* must be accompanied by the FIRST BSD license file in the root directory of */ 005 /* the project. */ 006 /*----------------------------------------------------------------------------*/ 007 008 package edu.wpi.first.wpilibj.communication; 009 010 import com.sun.cldc.jna.Function; 011 import com.sun.cldc.jna.NativeLibrary; 012 import com.sun.cldc.jna.Pointer; 013 import com.sun.squawk.platform.posix.LibCUtil; 014 015 /** 016 * Class exposing VxWorks semaphores. 017 * @author dtjones 018 */ 019 public class Semaphore { 020 Pointer m_semaphore; 021 022 /** Integer ms value indicating wait forever. */ 023 public static final int WAIT_FOREVER = -1; 024 025 static final int SEM_Q_FIFO = 0x00; /* first in first out queue */ 026 static final int SEM_Q_PRIORITY = 0x01; /* priority sorted queue */ 027 static final int SEM_DELETE_SAFE = 0x04; /* owner delete safe (mutex opt.) */ 028 static final int SEM_INVERSION_SAFE = 0x08; /* no priority inversion (mutex opt.) */ 029 static final int SEM_EVENTSEND_ERR_NOTIFY = 0x10; /* notify when eventRsrcSend fails */ 030 static final int SEM_INTERRUPTIBLE = 0x20; /* interruptible on RTP signal */ 031 032 /** 033 * Options to create a semaphore with. 034 */ 035 public static class Options { 036 int value = 0; 037 /** 038 * Set true to use a priority sorted queue, false to use first-in first-out 039 * @param priority 040 */ 041 public void setPrioritySorted(boolean priority) { 042 if (priority) value |= SEM_Q_PRIORITY; 043 else value &= ~SEM_Q_PRIORITY; 044 } 045 /** 046 * Set whether or not the semaphore is delete safe. 047 * @param delSafe True to make the semaphore delete safe. 048 */ 049 public void setDeleteSafe(boolean delSafe) { 050 if (delSafe) value |= SEM_DELETE_SAFE; 051 else value &= ~SEM_DELETE_SAFE; 052 } 053 /** 054 * Set whether the semaphore is inversion safe. 055 * @param invSafe True to set the semaphore to inversion safe. 056 */ 057 public void setInversionSafe(boolean invSafe) { 058 if (invSafe) value |= SEM_INVERSION_SAFE; 059 else value &= ~SEM_INVERSION_SAFE; 060 } 061 /** 062 * Set whether the semaphore should notify on an error. 063 * @param errNot True to set error notify. 064 */ 065 public void setErrorNotify(boolean errNot) { 066 if (errNot) value |= SEM_EVENTSEND_ERR_NOTIFY; 067 else value &= ~SEM_EVENTSEND_ERR_NOTIFY; 068 } 069 /** 070 * Set whether the semaphore is interruptable. 071 * @param intable True allows this semaphore to be interrupted. 072 */ 073 public void setInterruptable(boolean intable) { 074 if (intable) value |= SEM_INTERRUPTIBLE; 075 else value &= ~SEM_INTERRUPTIBLE; 076 } 077 } 078 079 private static Function semMCreateFn = NativeLibrary.getDefaultInstance().getFunction("semMCreate"); //SEM_ID semMCreate (int options); 080 private static Function semBCreateFn = NativeLibrary.getDefaultInstance().getFunction("semBCreate"); //SEM_ID semBCreate (int options, SEM_B_STATE initialState); 081 private static Function semCCreateFn = NativeLibrary.getDefaultInstance().getFunction("semCCreate"); //SEM_ID semCCreate (int options, int initialCount); 082 private static Function semDeleteFn = NativeLibrary.getDefaultInstance().getFunction("semDelete"); //STATUS semDelete (SEM_ID semId); 083 private static Function semFlushFn = NativeLibrary.getDefaultInstance().getFunction("semFlush"); //STATUS semFlush (SEM_ID semId); 084 private static Function semGiveFn = NativeLibrary.getDefaultInstance().getFunction("semGive"); //STATUS semGive (SEM_ID semId); 085 private static Function semTakeFn = NativeLibrary.getDefaultInstance().getFunction("semTake"); //STATUS semTake (SEM_ID semId, int timeout); 086 private static Function semTakeBlockingFn = NativeLibrary.getDefaultInstance().getBlockingFunction("semTake"); //STATUS semTake (SEM_ID semId, int timeout); 087 // private static Function semOpenFn = NativeLibrary.getDefaultInstance().getFunction("semOpen"); //SEM_ID semOpen (const char * name, SEM_TYPE type, int initState, int options, int mode, void * context); 088 // private static Function semInfoGetFn = NativeLibrary.getDefaultInstance().getFunction("semInfoGet"); //STATUS semInfoGet (SEM_ID semId, SEM_INFO *pInfo); 089 private static Function semCloseFn = NativeLibrary.getDefaultInstance().getFunction("semClose"); //STATUS semClose (SEM_ID semId); 090 // private static Function semUnlinkFn = NativeLibrary.getDefaultInstance().getFunction("semUnlink"); //STATUS semUnlink (const char * name); 091 092 private void checkStatus (int status) throws SemaphoreException{ 093 if (status != 0) { 094 throw new SemaphoreException(LibCUtil.errno()); 095 } 096 } 097 098 /** 099 * Create a new semaphore. 100 * @param options The options to create the semaphore with. 101 */ 102 public Semaphore (Options options) { 103 m_semaphore = new Pointer(semMCreateFn.call1(options.value), 0); 104 } 105 106 /** 107 * Create a semaphore with the given initial state. 108 * @param options The options to create the semaphore with. 109 * @param initialState The initial state for the semaphore to have. 110 */ 111 public Semaphore (Options options, boolean initialState) { 112 m_semaphore = new Pointer(semBCreateFn.call2(options.value,initialState?1:0), 0); 113 } 114 115 /** 116 * Create a counting semaphore with the given value. 117 * @param options The options to create the semaphore with. 118 * @param count The initial count for the semaphore to hold. 119 */ 120 public Semaphore (Options options, int count) { 121 m_semaphore = new Pointer(semCCreateFn.call2(options.value, count), 0); 122 } 123 124 /** 125 * Get the pointer to the native semaphore. 126 * @return Pointer to the native semaphore. 127 */ 128 public Pointer getPointer() { 129 return m_semaphore; 130 } 131 132 /** 133 * Unblock every task that is blocked by the semaphore. 134 */ 135 public void flush() throws SemaphoreException{ 136 checkStatus(semFlushFn.call1(m_semaphore)); 137 } 138 139 /** 140 * Release the semaphore. 141 */ 142 public void give() throws SemaphoreException{ 143 checkStatus(semGiveFn.call1(m_semaphore)); 144 } 145 146 /** 147 * Take the semaphore. Block for timeout milliseconds. 148 * @param timeout The maximum time in milliseconds to block for the semaphore. 149 * @throws SemaphoreException if the lock can't be take in timeout seconds, or some other semaphore error condition occurs. 150 */ 151 public void takeMillis(int timeout) throws SemaphoreException{ 152 checkStatus(semTakeBlockingFn.call2(m_semaphore, timeout)); 153 } 154 155 /** 156 * Take the semaphore. Block forever until semaphore is available. 157 * @throws SemaphoreException if some semaphore error condition occurs. 158 */ 159 public void takeForever() throws SemaphoreException{ 160 takeMillis(WAIT_FOREVER); 161 } 162 163 /* 164 * Non-blocking version of take(). Try to take the Semaphore. 165 * 166 * @return If succeeded return true, otherwise return false. 167 * @throws SemaphoreException if some semaphore error condition occurs. 168 */ 169 public boolean tryTake() throws SemaphoreException{ 170 int result = semTakeFn.call2(m_semaphore, 0); 171 if (result == 0) { 172 return true; 173 } else { 174 int errno = LibCUtil.errno(); 175 if (errno == SemaphoreException.S_objLib_OBJ_UNAVAILABLE) { 176 return false; 177 } else { 178 throw new SemaphoreException(errno); 179 } 180 } 181 } 182 183 /** 184 * Close the semaphore. 185 */ 186 public void close () throws SemaphoreException{ 187 checkStatus(semCloseFn.call1(m_semaphore)); 188 } 189 190 /** 191 * Release all resources associated with the semaphore. 192 */ 193 public void free () throws SemaphoreException{ 194 checkStatus(semDeleteFn.call1(m_semaphore)); 195 } 196 }