Changeset 5304 for trunk/oscam-simples.c
- Timestamp:
- 05/28/11 01:47:42 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/oscam-simples.c
r5298 r5304 1010 1010 memcpy(dest, source, 6); 1011 1011 } 1012 1013 /* Internal function of cs_lock and cs_trylock to prepare adding an entry to the list. Do not call this externally. */ 1014 struct s_client* cs_preparelock(struct s_client *cl, pthread_mutex_t *mutex){ 1015 if(cl){ 1016 // WebIf doesn't have real clients... 1017 if(cl->typ == 'h') return NULL; 1018 if(cl->mutexstore_alloc <= cl->mutexstore_used){ 1019 void *ret; 1020 if(cl->mutexstore_alloc == 0) 1021 ret = cs_malloc(&cl->mutexstore, 8 * sizeof(pthread_mutex_t *), -1); 1022 else 1023 ret = cs_realloc(&cl->mutexstore, (cl->mutexstore_used + 8) * sizeof(pthread_mutex_t *), -1); 1024 if(ret != NULL){ 1025 cl->mutexstore_alloc = cl->mutexstore_used + 8; 1026 cl->mutexstore[cl->mutexstore_used] = mutex; 1027 } else { 1028 cl->mutexstore_alloc = 0; 1029 cl->mutexstore_used = 0; 1030 } 1031 } else { 1032 cl->mutexstore[cl->mutexstore_used] = mutex; 1033 } 1034 } 1035 return cl; 1036 } 1037 1038 /* Replacement for pthread_mutex_lock which waits a maximum of about 3 seconds. 1039 Locks are saved to the client structure so that they can get cleaned up if the thread was interrupted while holding a lock. */ 1040 int32_t cs_lock(pthread_mutex_t *mutex){ 1041 int32_t result, oldtype, cnt = 0; 1042 /* Make sure that we won't get interrupted while getting the lock */ 1043 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldtype); 1044 struct s_client *cl = cs_preparelock(cur_client(), mutex); 1045 do{ 1046 result = pthread_mutex_trylock(mutex); 1047 ++cnt; 1048 cs_sleepms(100); 1049 } while (result == EBUSY && cnt < 30); 1050 if(result == 0 && cl) 1051 cl->mutexstore_used++; 1052 pthread_setcancelstate(oldtype, NULL); 1053 pthread_testcancel(); 1054 if(result == EBUSY){ 1055 cs_log("A log couldn't be obtained within 3 seconds. Possibly a deadlock happened."); 1056 } 1057 return result; 1058 } 1059 1060 /* Encapsulates pthread_mutex_trylock. If a lock is gained it is saved to the client structure so that it can get cleaned up if the thread was interrupted while holding a lock. */ 1061 int32_t cs_trylock(pthread_mutex_t *mutex){ 1062 int32_t result, oldtype; 1063 /* Make sure that we won't get interrupted while getting the lock */ 1064 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldtype); 1065 struct s_client *cl = cs_preparelock(cur_client(), mutex); 1066 if((result=pthread_mutex_trylock(mutex)) == 0 && cl) 1067 cl->mutexstore_used++; 1068 pthread_setcanceltype(oldtype, NULL); 1069 pthread_testcancel(); 1070 return result; 1071 } 1072 1073 /* Encapsulates pthread_mutex_unlock and removes the given mutex from the client structure 1074 If the given lock was not previously locked by the current thread, nothing is done. */ 1075 int32_t cs_unlock(pthread_mutex_t *mutex){ 1076 struct s_client *cl = cur_client(); 1077 if(cl && cl->typ != 'h'){ 1078 uint16_t i; 1079 /* new mutexes get appended to the end so it should be more efficient to search from end to beginning */ 1080 for(i = cl->mutexstore_used; i > 0; --i){ 1081 if(cl->mutexstore[i - 1] == mutex){ 1082 int32_t result, oldtype; 1083 /* Make sure that we won't get interrupted while returning the lock */ 1084 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldtype); 1085 if(i < cl->mutexstore_used){ 1086 // Move mutex to last position to prepare removal 1087 do { 1088 cl->mutexstore[i - 1] = cl->mutexstore[i]; 1089 ++i; 1090 } while (i < cl->mutexstore_used); 1091 cl->mutexstore[cl->mutexstore_used - 1] = mutex; 1092 } 1093 if((result=pthread_mutex_unlock(mutex)) == 0) 1094 cl->mutexstore_used--; 1095 pthread_setcanceltype(oldtype, NULL); 1096 pthread_testcancel(); 1097 return result; 1098 } 1099 } 1100 return EINVAL; 1101 } else return pthread_mutex_unlock(mutex); 1102 } 1103 1104 /* Releases all locks still held by the current client. */ 1105 void cs_cleanlocks(){ 1106 struct s_client *cl = cur_client(); 1107 if(cl && cl->mutexstore_alloc > 0){ 1108 uint16_t i; 1109 for(i = 0; i < cl->mutexstore_used; ++i){ 1110 pthread_mutex_unlock(cl->mutexstore[i]); 1111 } 1112 cl->mutexstore_used = 0; 1113 cl->mutexstore_alloc = 0; 1114 free(cl->mutexstore); 1115 } 1116 }
Note:
See TracChangeset
for help on using the changeset viewer.