Choco OS  V.0.16.9.0
Join to the chocolate world
oc_service.c
Go to the documentation of this file.
1 
27 #include <oc_service.h>
28 #include <oc_object.h>
29 #include <oc_process.h>
30 #include <oc_string.h>
31 #include <oc_streamman.h>
32 #include <oc_intman.h>
33 #include <oc_processman.h>
34 
40 #define _________________________________________TYPES_SECTION______________________________________________________________________________
41 
42 struct Service_t
43 {
44  oC_ObjectControl_t ObjectControl;
45  oC_Process_t Process;
46  oC_Thread_t MainThread;
47  oC_DefaultString_t Name;
48  oC_Service_MainFunction_t MainFunction;
49  oC_Service_StartFunction_t StartFunction;
50  oC_Service_StopFunction_t StopFunction;
51  oC_MemorySize_t MainThreadStackSize;
52  oC_Process_Priority_t Priority;
53  oC_MemorySize_t HeapMapSize;
54  bool Started;
55  oC_Service_Context_t Context;
56  oC_Module_RequiredArray_t RequiredModules;
57 };
58 
59 #undef _________________________________________TYPES_SECTION______________________________________________________________________________
60 
66 #define _________________________________________PROTOTYPES_SECTION_________________________________________________________________________
67 
68 static bool AreRequiredModulesEnabled ( oC_Service_t Service );
69 static void ServiceThread ( oC_Service_t Service );
70 
71 #undef _________________________________________PROTOTYPES_SECTION_________________________________________________________________________
72 
73 
74 
80 #define _________________________________________GLOBALS_SECTION____________________________________________________________________________
81 
82 static const oC_Allocator_t Allocator = {
83  .Name = "Service"
84 };
85 
86 #undef _________________________________________GLOBALS_SECTION____________________________________________________________________________
87 
88 
89 
95 #define _________________________________________INTERFACE_SECTION__________________________________________________________________________
96 
97 //==========================================================================================================================================
110 //==========================================================================================================================================
112 {
113  oC_Service_t service = NULL;
114  oC_Stream_t stream = oC_StreamMan_GetStdErrorStream();
115 
116  if(
117  oC_SaveIfFalse("Service::New: Registration - " , isaddresscorrect(Registration) , oC_ErrorCode_WrongAddress )
118  && oC_SaveIfFalse("Service::New: Name - " , isaddresscorrect(Registration->Name) , oC_ErrorCode_WrongAddress )
119  && oC_SaveIfFalse("Service::New: Name - " , strlen(Registration->Name) > 0 , oC_ErrorCode_StringIsEmpty )
120  && oC_SaveIfFalse("Service::New: StartFunction - " , isaddresscorrect(Registration->StartFunction) , oC_ErrorCode_WrongAddress )
121  && oC_SaveIfFalse("Service::New: StopFunction - " , isaddresscorrect(Registration->StopFunction) , oC_ErrorCode_WrongAddress )
122  && oC_SaveIfFalse("Service::New: MainFunction - " , isaddresscorrect(Registration->MainFunction) , oC_ErrorCode_WrongAddress )
123  )
124  {
125 
126  service = kmalloc( sizeof(struct Service_t), &Allocator, AllocationFlags_ZeroFill );
127 
128  if(oC_SaveIfFalse("Service::New: Main object - ", service != NULL, oC_ErrorCode_AllocationError))
129  {
130  oC_User_t user = getcuruser();
131  strncpy(service->Name, Registration->Name, sizeof(service->Name));
132 
133  user = user == NULL ? getrootuser() : user;
134 
135  service->Process = oC_Process_New( Registration->Priority, service->Name, user, Registration->HeapMapSize, NULL, stream, stream);
136  service->MainThread = oC_Thread_New ( Registration->Priority, Registration->MainThreadStackSize, service->Process, service->Name, (oC_Thread_Function_t)ServiceThread, service );
137  service->MainFunction = Registration->MainFunction;
138  service->StartFunction = Registration->StartFunction;
139  service->StopFunction = Registration->StopFunction;
140  service->MainThreadStackSize = Registration->MainThreadStackSize;
141  service->Priority = Registration->Priority;
142  service->HeapMapSize = Registration->HeapMapSize;
143  service->Context = NULL;
144  service->Started = false;
145 
146  memcpy(service->RequiredModules,Registration->RequiredModules,sizeof(service->RequiredModules));
147 
148  if(
149  oC_SaveIfFalse("Service::New: Process - ", oC_Process_IsCorrect(service->Process) , oC_ErrorCode_AllocationError )
150  && oC_SaveIfFalse("Service::New: Thread - " , oC_Thread_IsCorrect(service->MainThread) , oC_ErrorCode_AllocationError )
151  )
152  {
153  service->ObjectControl = oC_CountObjectControl(service, oC_ObjectId_Service);
154 
155  bool allocationLimitSet = oC_Process_SetAllocationLimit(service->Process, Registration->AllocationLimit);
156  oC_SaveIfFalse("Service::New: Cannot set allocation limit ", allocationLimitSet, oC_ErrorCode_InternalDataAreDamaged);
157  }
158  }
159  }
160 
161  return service;
162 }
163 
164 //==========================================================================================================================================
174 //==========================================================================================================================================
176 {
177  bool deleted = false;
178 
179  if(
180  oC_SaveIfFalse("Service::Delete ", isram(Service) , oC_ErrorCode_AddressNotInRam )
181  && oC_SaveIfFalse("Service::Delete ", oC_Service_IsCorrect(*Service) , oC_ErrorCode_ObjectNotCorrect )
182  )
183  {
184  oC_IntMan_EnterCriticalSection();
185  oC_Service_t service = *Service;
186  oC_Process_t process = service->Process;
187  oC_Thread_t thread = service->MainThread;
188  bool memoryReleased = kfree(service, AllocationFlags_Default);
189  bool processKilled = oC_Process_Kill( process );
190  bool threadDeleted = oC_Thread_Delete(&thread);
191  bool processDeleted = oC_Process_Delete(&process);
192 
193  *Service = NULL;
194 
195  if(
196  oC_SaveIfFalse("Service::Delete: Main object - ", memoryReleased, oC_ErrorCode_ReleaseError )
197  && oC_SaveIfFalse("Service::Delete: Process - " , processKilled , oC_ErrorCode_CannotKillProcess )
198  && oC_SaveIfFalse("Service::Delete: Thread - " , threadDeleted , oC_ErrorCode_ReleaseError )
199  && oC_SaveIfFalse("Service::Delete: Process - " , processDeleted, oC_ErrorCode_ReleaseError )
200  )
201  {
202  deleted = true;
203  }
204 
205  oC_IntMan_ExitCriticalSection();
206  }
207 
208  return deleted;
209 }
210 
211 //==========================================================================================================================================
215 //==========================================================================================================================================
217 {
218  return isram(Service) && oC_CheckObjectControl(Service, oC_ObjectId_Service, Service->ObjectControl );
219 }
220 
221 //==========================================================================================================================================
231 //==========================================================================================================================================
232 oC_ErrorCode_t oC_Service_Start( oC_Service_t Service )
233 {
234  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
235  oC_Stream_t stream = oC_StreamMan_GetStdErrorStream();
236 
237  if(
238  ErrorCondition( oC_Service_IsCorrect(Service) == true , oC_ErrorCode_ObjectNotCorrect )
239  && ErrorCondition( oC_Service_IsActive(Service) == false , oC_ErrorCode_ServiceAlreadyStarted )
240  && ErrorCondition( AreRequiredModulesEnabled(Service) == true , oC_ErrorCode_RequiredModuleNotEnabled )
241  )
242  {
243  if( oC_Process_IsCorrect(Service->Process) == false || oC_Thread_IsCorrect(Service->MainThread) == false )
244  {
245  Service->Process = oC_Process_New( Service->Priority, Service->Name, getcuruser(), Service->HeapMapSize, NULL, stream, stream);
246  Service->MainThread = oC_Thread_New ( Service->Priority, Service->MainThreadStackSize, Service->Process, Service->Name, (oC_Thread_Function_t)ServiceThread, Service );
247  }
248  if(
249  ErrorCondition( oC_Process_IsCorrect(Service->Process) , oC_ErrorCode_AllocationError )
250  && ErrorCondition( oC_Thread_IsCorrect(Service->MainThread) , oC_ErrorCode_AllocationError )
251  && ErrorCode ( oC_ProcessMan_AddProcess(Service->Process) )
252  && ErrorCondition( oC_Thread_Run( Service->MainThread ) , oC_ErrorCode_CannotRunThread )
253  )
254  {
255  errorCode = oC_ErrorCode_None;
256  }
257  }
258 
259  return errorCode;
260 }
261 
262 //==========================================================================================================================================
272 //==========================================================================================================================================
273 oC_ErrorCode_t oC_Service_Stop( oC_Service_t Service )
274 {
275  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
276 
277  if(
278  ErrorCondition( oC_Service_IsCorrect(Service) == true , oC_ErrorCode_ObjectNotCorrect )
279  && ErrorCondition( oC_Service_IsActive(Service) == true , oC_ErrorCode_ServiceNotStarted )
280  )
281  {
282  oC_IntMan_EnterCriticalSection();
283 
284  if(
285  Service->Started == false
286  || (
287  ErrorCondition( isaddresscorrect(Service->StopFunction), oC_ErrorCode_WrongAddress )
288  && ErrorCode ( Service->StopFunction( &Service->Context ) )
289  )
290  )
291  {
292  if( ErrorCode( oC_Process_Kill(Service->Process) ) )
293  {
294  Service->Process = NULL;
295  Service->MainThread = NULL;
296  errorCode = oC_ErrorCode_None;
297  }
298  }
299 
300  oC_IntMan_ExitCriticalSection();
301  }
302 
303  return errorCode;
304 }
305 
306 //==========================================================================================================================================
310 //==========================================================================================================================================
312 {
313  return oC_Service_IsCorrect(Service) && oC_Process_IsActive(Service->Process);
314 }
315 
316 //==========================================================================================================================================
320 //==========================================================================================================================================
321 const char * oC_Service_GetName( oC_Service_t Service )
322 {
323  const char * name = "incorrect service";
324 
325  if(oC_Service_IsCorrect(Service))
326  {
327  name = Service->Name;
328  }
329 
330  return name;
331 }
332 
333 //==========================================================================================================================================
337 //==========================================================================================================================================
339 {
340  oC_Process_t process = NULL;
341 
342  if(oC_Service_IsCorrect(Service))
343  {
344  process = Service->Process;
345  }
346 
347  return process;
348 }
349 
350 #undef _________________________________________INTERFACE_SECTION__________________________________________________________________________
351 
357 #define _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
358 
359 
360 //==========================================================================================================================================
364 //==========================================================================================================================================
366 {
367  bool allEnabled = true;
368 
369  oC_ARRAY_FOREACH_IN_ARRAY(Service->RequiredModules,moduleReference)
370  {
371  if((*moduleReference) > oC_Module_None && (*moduleReference) < oC_Module_NumberOfModules)
372  {
373  if(oC_Module_IsTurnedOn(*moduleReference) == false)
374  {
375  kdebuglog( oC_LogType_Info, "Cannot start service %s - module ID = %d is not enabled", Service->Name, *moduleReference );
376  allEnabled = false;
377  break;
378  }
379  }
380  }
381 
382  return allEnabled;
383 }
384 
385 //==========================================================================================================================================
389 //==========================================================================================================================================
390 static void ServiceThread( oC_Service_t Service )
391 {
392  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
393 
394  if(
395  oC_SaveIfFalse("ServiceThread: Service is not correct - ", oC_Service_IsCorrect(Service) , oC_ErrorCode_ObjectNotCorrect )
396  && oC_SaveIfFalse("ServiceThread: StartFunction - " , isaddresscorrect(Service->StartFunction) , oC_ErrorCode_WrongAddress )
397  && oC_SaveIfFalse("ServiceThread: MainFunction - " , isaddresscorrect(Service->MainFunction) , oC_ErrorCode_WrongAddress )
398  && oC_SaveIfFalse("ServiceThread: StopFunction - " , isaddresscorrect(Service->StopFunction) , oC_ErrorCode_WrongAddress )
399  )
400  {
401  if(oC_SaveIfErrorOccur(Service->Name, errorCode = Service->StartFunction( &Service->Context )))
402  {
403  kdebuglog( oC_LogType_Track , "The service '%s' has been started", Service->Name );
404  oC_SaveIfErrorOccur(Service->Name, errorCode = Service->MainFunction ( Service->Context ));
405  kdebuglog( oC_ErrorOccur(errorCode) ? oC_LogType_Error : oC_LogType_Track, "The service '%s' has finished with status '%s'", Service->Name, oC_GetErrorString(errorCode));
406  oC_SaveIfErrorOccur(Service->Name, errorCode = Service->StopFunction ( &Service->Context ));
407  kdebuglog( oC_ErrorOccur(errorCode) ? oC_LogType_Error : oC_LogType_Track, "The service '%s' has been stopped with status: '%s'", Service->Name, oC_GetErrorString(errorCode));
408  }
409  else
410  {
411  kdebuglog( oC_LogType_Error, "Cannot start service '%s' because of error '%s'", Service->Name , oC_GetErrorString(errorCode));
412  }
413  }
414 }
415 
416 #undef _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
417 
418 
419 
420 
const char * Name
Definition: oc_stdlib.h:161
identifier for allocations
Definition: oc_stdlib.h:159
The file with interface for process manager.
oC_Service_t oC_Service_New(const oC_Service_Registration_t *Registration)
allocates memory for a new service
Definition: oc_service.c:111
bool oC_Service_IsCorrect(oC_Service_t Service)
returns true if the service object is correct
Definition: oc_service.c:216
Definition: oc_user.c:43
oC_ErrorCode_t oC_Service_Stop(oC_Service_t Service)
stops the service
Definition: oc_service.c:273
const char * oC_Service_GetName(oC_Service_t Service)
returns name of the service
Definition: oc_service.c:321
The file with helper macros for managing objects.
static bool AreRequiredModulesEnabled(oC_Service_t Service)
checks if all required modules are enabled
Definition: oc_service.c:365
static bool oC_Module_IsTurnedOn(oC_Module_t Module)
checks if the module is turned on
Definition: oc_module.h:121
The file with interface for stream manager.
uint32_t oC_ObjectControl_t
stores object control value
Definition: oc_object.h:141
bool oC_Service_Delete(oC_Service_t *Service)
releases memory allocated for a service
Definition: oc_service.c:175
The file with interface for interrupt manager.
static oC_ObjectControl_t oC_CountObjectControl(void *ObjectPointer, oC_ObjectId_t ObjectId)
counts object control for object
Definition: oc_object.h:168
static bool oC_CheckObjectControl(void *ObjectPointer, oC_ObjectId_t ObjectId, oC_ObjectControl_t ObjectControl)
checks if object control is correct
Definition: oc_object.h:203
bool oC_Service_IsActive(oC_Service_t Service)
returns true if the service is correct and active
Definition: oc_service.c:311
stores ETH context
Definition: oc_eth.c:97
The file with interface for process mechanism.
The file with interface for string library.
interface for handling services
const char * oC_GetErrorString(oC_ErrorCode_t ErrorCode)
Definition: oc_errors.c:115
oC_ErrorCode_t oC_Service_Start(oC_Service_t Service)
starts the service
Definition: oc_service.c:232
oC_Process_t oC_Service_GetProcess(oC_Service_t Service)
returns process associated with the service
Definition: oc_service.c:338
#define NULL
pointer to a zero
Definition: oc_null.h:37
static void ServiceThread(oC_Service_t Service)
main thread for services
Definition: oc_service.c:390