/src/Nucleus/Process.c

https://github.com/dprevost/newpso · C · 287 lines · 196 code · 50 blank · 41 comment · 45 complexity · 81abac797efa96a2a9f1d0421a5199cc MD5 · raw file

  1. /*
  2. * Copyright (C) 2007-2010 Daniel Prevost <dprevost@photonsoftware.org>
  3. *
  4. * This file is part of Photon (photonsoftware.org).
  5. *
  6. * This file may be distributed and/or modified under the terms of the
  7. * GNU General Public License version 2 or version 3 as published by the
  8. * Free Software Foundation and appearing in the file COPYING.GPL2 and
  9. * COPYING.GPL3 included in the packaging of this software.
  10. *
  11. * Licensees holding a valid Photon Commercial license can use this file
  12. * in accordance with the terms of their license.
  13. *
  14. * This software is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. */
  18. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */
  19. #include "Nucleus/Process.h"
  20. #include "Nucleus/MemoryAllocator.h"
  21. #include "Nucleus/SessionContext.h"
  22. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */
  23. bool psonProcessAddSession( psonProcess * process,
  24. void * pApiSession,
  25. psonSession ** ppSession,
  26. psonSessionContext * pContext )
  27. {
  28. psonSession * pCurrentBuffer;
  29. bool ok = false;
  30. PSO_PRE_CONDITION( process != NULL );
  31. PSO_PRE_CONDITION( pApiSession != NULL );
  32. PSO_PRE_CONDITION( ppSession != NULL );
  33. PSO_PRE_CONDITION( pContext != NULL );
  34. PSO_TRACE_ENTER_NUCLEUS( pContext );
  35. *ppSession = NULL;
  36. /* For recovery purposes, always lock before doing anything! */
  37. if ( psonLock( &process->memObject, pContext ) ) {
  38. pCurrentBuffer = (psonSession*)
  39. psonMallocBlocks( pContext->pAllocator, PSON_ALLOC_ANY, 1, pContext );
  40. if ( pCurrentBuffer != NULL ) {
  41. ok = psonSessionInit( pCurrentBuffer, pApiSession, pContext );
  42. PSO_PRE_CONDITION( ok == true || ok == false );
  43. if ( ok ) {
  44. psonLinkNodeInit( &pCurrentBuffer->node, pContext );
  45. psonLinkedListPutLast( &process->listOfSessions,
  46. &pCurrentBuffer->node,
  47. pContext );
  48. *ppSession = pCurrentBuffer;
  49. }
  50. else {
  51. psonFreeBlocks( pContext->pAllocator,
  52. PSON_ALLOC_ANY,
  53. (unsigned char *)pCurrentBuffer,
  54. 1, pContext );
  55. }
  56. }
  57. else {
  58. psocSetError( &pContext->errorHandler,
  59. g_psoErrorHandle,
  60. PSO_NOT_ENOUGH_PSO_MEMORY );
  61. }
  62. /*
  63. * If the init was a success, this is now initialized. We must
  64. * add the previouslock otherwise... the unlock will fail (segv).
  65. */
  66. if ( pContext->lockOffsets != NULL ) {
  67. pContext->lockOffsets[*pContext->numLocks] = SET_OFFSET(pContext->pBaseAddress, &process->memObject);
  68. (*pContext->numLocks)++;
  69. }
  70. psonUnlock( &process->memObject, pContext );
  71. }
  72. else {
  73. psocSetError( &pContext->errorHandler,
  74. g_psoErrorHandle,
  75. PSO_ENGINE_BUSY );
  76. }
  77. PSO_TRACE_EXIT_NUCLEUS( pContext, ok );
  78. return ok;
  79. }
  80. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */
  81. #if defined(PSO_USE_TRACE)
  82. void psonProcessDump( psonProcess * process,
  83. int indent,
  84. psonSessionContext * pContext )
  85. {
  86. DO_INDENT( pContext, indent );
  87. fprintf( pContext->tracefp, "psonProcess (%p) offset = "PSO_PTRDIFF_T_FORMAT"\n",
  88. process, SET_OFFSET(pContext->pBaseAddress, process) );
  89. if ( process == NULL ) return;
  90. psonMemObjectDump( &process->memObject, indent + 2, pContext );
  91. psonLinkNodeDump( &process->node, indent + 2, pContext );
  92. DO_INDENT( pContext, indent + 2 );
  93. fprintf( pContext->tracefp, "Process pid: %ud\n", process->pid );
  94. psonLinkedListDump( &process->listOfSessions, indent + 2, pContext );
  95. if ( process->processIsTerminating ) {
  96. DO_INDENT( pContext, indent + 2 );
  97. fprintf( pContext->tracefp, "This process is ending\n" );
  98. }
  99. else {
  100. DO_INDENT( pContext, indent + 2 );
  101. fprintf( pContext->tracefp, "This process is not ending\n" );
  102. }
  103. psonBlockGroupDump( &process->blockGroup, indent + 2, pContext );
  104. DO_INDENT( pContext, indent );
  105. fprintf( pContext->tracefp, "psonProcess END\n" );
  106. }
  107. #endif
  108. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */
  109. void psonProcessFini( psonProcess * process,
  110. psonSessionContext * pContext )
  111. {
  112. psonSession * pSession = NULL;
  113. psonLinkNode * pNode = NULL;
  114. bool ok;
  115. PSO_PRE_CONDITION( process != NULL );
  116. PSO_PRE_CONDITION( pContext != NULL );
  117. PSO_PRE_CONDITION( process->memObject.objType == PSON_IDENT_PROCESS );
  118. PSO_TRACE_ENTER_NUCLEUS( pContext );
  119. /*
  120. * Eliminate all sessions in the list. This is probably not needed
  121. * as we will release the blocks of memory to the allocator as the
  122. * last step. This might be reviewed eventually.
  123. */
  124. while ( psonLinkedListPeakFirst( &process->listOfSessions,
  125. &pNode,
  126. pContext ) ) {
  127. pSession = (psonSession*)
  128. ((char*)pNode - offsetof( psonSession, node ));
  129. ok = psonProcessRemoveSession( process, pSession, pContext );
  130. PSO_POST_CONDITION( ok == true || ok == false );
  131. }
  132. /*
  133. * This will remove the blocks of allocated memory.
  134. * It must be the last operation on that piece of memory.
  135. */
  136. psonMemObjectFini( &process->memObject, PSON_ALLOC_ANY, pContext );
  137. PSO_TRACE_EXIT_NUCLEUS( pContext, true );
  138. }
  139. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */
  140. bool psonProcessGetFirstSession( psonProcess * process,
  141. psonSession ** ppSession,
  142. psonSessionContext * pContext )
  143. {
  144. psonLinkNode * pNode = NULL;
  145. bool ok;
  146. PSO_PRE_CONDITION( process != NULL );
  147. PSO_PRE_CONDITION( ppSession != NULL );
  148. PSO_PRE_CONDITION( pContext != NULL );
  149. PSO_TRACE_ENTER_NUCLEUS( pContext );
  150. ok = psonLinkedListPeakFirst( &process->listOfSessions, &pNode, pContext );
  151. if ( ok ) {
  152. *ppSession = (psonSession *)
  153. ((char*)pNode - offsetof( psonSession, node ));
  154. }
  155. PSO_TRACE_EXIT_NUCLEUS( pContext, ok );
  156. return ok;
  157. }
  158. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */
  159. bool psonProcessGetNextSession( psonProcess * process,
  160. psonSession * pCurrent,
  161. psonSession ** ppNext,
  162. psonSessionContext * pContext )
  163. {
  164. psonLinkNode * pNode = NULL;
  165. bool ok;
  166. PSO_PRE_CONDITION( process != NULL );
  167. PSO_PRE_CONDITION( pCurrent != NULL );
  168. PSO_PRE_CONDITION( pContext != NULL );
  169. PSO_PRE_CONDITION( ppNext != NULL );
  170. PSO_TRACE_ENTER_NUCLEUS( pContext );
  171. ok = psonLinkedListPeakNext( &process->listOfSessions,
  172. &pCurrent->node,
  173. &pNode,
  174. pContext );
  175. if ( ok ) {
  176. *ppNext = (psonSession*)
  177. ((char*)pNode - offsetof( psonSession, node ));
  178. }
  179. PSO_TRACE_EXIT_NUCLEUS( pContext, ok );
  180. return ok;
  181. }
  182. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */
  183. bool psonProcessInit( psonProcess * process,
  184. pid_t pid,
  185. psonSessionContext * pContext )
  186. {
  187. psoErrors errcode;
  188. PSO_PRE_CONDITION( process != NULL );
  189. PSO_PRE_CONDITION( pContext != NULL );
  190. PSO_PRE_CONDITION( pid > 0 );
  191. PSO_TRACE_ENTER_NUCLEUS( pContext );
  192. errcode = psonMemObjectInit( &process->memObject,
  193. PSON_IDENT_PROCESS,
  194. &process->blockGroup,
  195. 1,
  196. pContext ); /* A single block */
  197. if ( errcode != PSO_OK ) {
  198. psocSetError( &pContext->errorHandler,
  199. g_psoErrorHandle,
  200. errcode );
  201. PSO_TRACE_EXIT_NUCLEUS( pContext, false );
  202. return false;
  203. }
  204. process->pid = pid;
  205. process->processIsTerminating = false;
  206. psonLinkedListInit( &process->listOfSessions, pContext );
  207. PSO_TRACE_EXIT_NUCLEUS( pContext, true );
  208. return true;
  209. }
  210. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */
  211. bool psonProcessRemoveSession( psonProcess * process,
  212. psonSession * pSession,
  213. psonSessionContext * pContext )
  214. {
  215. PSO_PRE_CONDITION( process != NULL );
  216. PSO_PRE_CONDITION( pSession != NULL );
  217. PSO_PRE_CONDITION( pContext != NULL );
  218. PSO_TRACE_ENTER_NUCLEUS( pContext );
  219. /* For recovery purposes, always lock before doing anything! */
  220. if ( psonLock( &process->memObject, pContext ) ) {
  221. psonLinkedListRemoveItem( &process->listOfSessions,
  222. &pSession->node,
  223. pContext );
  224. psonSessionFini( pSession, pContext );
  225. psonUnlock( &process->memObject, pContext );
  226. }
  227. else {
  228. psocSetError( &pContext->errorHandler,
  229. g_psoErrorHandle,
  230. PSO_ENGINE_BUSY );
  231. PSO_TRACE_EXIT_NUCLEUS( pContext, false );
  232. return false;
  233. }
  234. PSO_TRACE_EXIT_NUCLEUS( pContext, true );
  235. return true;
  236. }
  237. /* --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- */