// task was supposed to release it's resources, // but we do our cleanup anyway // NOTE: we don't need to unsubscribe from events
osTaskRelease(task);
}
if (!srcTask) {
osLog(LOG_ERROR, "ERROR: Failed to find task to free event: evtType=%08" PRIX32 "\n", evtType); return;
}
if (taggedPtrIsPtr(evtFreeInfo) && taggedPtrToPtr(evtFreeInfo)) { if (osTaskIsChre(srcTask) && (evtType >> 16) == EVT_PRIVATE_CLASS_CHRE) {
osChreFreeEvent(fromTid,
(void (*)(uint16_t, void *))taggedPtrToPtr(evtFreeInfo),
evtType & EVT_MASK, evtData);
} else { // this is for internal non-CHRE tasks, and CHRE tasks // System may schedule non-CHRE events on behalf of CHRE app; // this is the place we release them struct Task *preempted = osSetCurrentTask(srcTask);
((EventFreeF)taggedPtrToPtr(evtFreeInfo))(evtData);
osSetCurrentTask(preempted);
}
} elseif (taggedPtrIsUint(evtFreeInfo)) { // this is for external non-CHRE tasks struct AppEventFreeData fd = {.evtType = evtType, .evtData = evtData};
osTaskHandle(srcTask, EVT_APP_FREE_EVT_DATA, OS_SYSTEM_TID, &fd);
}
osTaskAddIoCount(srcTask, -1);
}
staticvoid handleEventFreeing(uint32_t evtType, void *evtData, TaggedPtr evtFreeData) // watch out, this is synchronous
{ struct Task *srcTask = osTaskFindByTid(EVENT_GET_ORIGIN(evtType));
if (!srcTask) {
osLog(LOG_ERROR, "ERROR: Failed to find task to free event: evtType=%08" PRIX32 "\n", evtType); return;
}
// release non-CHRE event; we can't determine if this is CHRE or non-CHRE event, but // this method is only called to release non-CHRE events, so we make use of that fact
if (taggedPtrIsPtr(evtFreeData) && taggedPtrToPtr(evtFreeData)) { // this is for internal non-CHRE tasks, and CHRE tasks // System may schedule non-CHRE events on behalf of CHRE app; // this is the place we release them struct Task *preempted = osSetCurrentTask(srcTask);
((EventFreeF)taggedPtrToPtr(evtFreeData))(evtData);
osSetCurrentTask(preempted);
} elseif (taggedPtrIsUint(evtFreeData)) { // this is for external non-CHRE tasks struct AppEventFreeData fd = {.evtType = EVENT_GET_EVENT(evtType), .evtData = evtData};
osTaskHandle(srcTask, EVT_APP_FREE_EVT_DATA, OS_SYSTEM_TID, &fd);
}
// available space check: we could truncate size, instead of disallowing it, // but we know that we performed validation on the size before, in *Create call, // and it was fine, so this must be a programming error, and so we fail. // on a side note: size may grow or shrink compared to original estimate. // typically it shrinks, since we skip some header info and padding, as well // as signature blocks, but it is possible that at some point we may produce // more data for some reason. At that time the logic here may need to change if (osSegmentSizeGetNext(storageSeg, segDataSize) > (struct Segment*)end) returnfalse;
memset(buf, 0, sizeof(buf)); while (size > 0) {
uint32_t flashSz = size > sizeof(buf) ? sizeof(buf) : size; // keep trying to zero-out stuff even in case of intermittent failures. // flash write may occasionally fail on some byte, but it is not good enough // reason to not rewrite other bytes bool res = osWriteShared(p, buf, flashSz);
done = done && res;
size -= flashSz;
p += flashSz;
}
task = osAllocTask(); if (!task) {
osLog(LOG_WARN, "External app id %016" PRIX64 " @ %p cannot be used as too many apps already exist.\n", app->hdr.appId, app); return NULL;
}
task->app = app; bool done = (app->hdr.fwFlags & FL_APP_HDR_INTERNAL) ?
cpuInternalAppLoad(task->app, &task->platInfo) :
cpuAppLoad(task->app, &task->platInfo);
if (!done) {
osLog(LOG_WARN, "App @ %p ID %016" PRIX64 " failed to load\n", app, app->hdr.appId);
osFreeTask(task);
task = NULL;
}
return task;
}
staticvoid osUnloadApp(struct Task *task)
{ // this is called on task that has stopped running, or had never run
cpuAppUnload(task->app, &task->platInfo);
osFreeTask(task);
}
while (osSegmentIteratorNext(it)) {
seg = it->seg; if (!seg) break; if (seg->state == SEG_ST_EMPTY) break; if (seg->state != SEG_ST_VALID) continue;
app = osSegmentGetData(seg); if (func(data, app)) returntrue;
}
osSegmentIteratorInit(&it); while (osExtAppFind(&it, func, data)) {
app = osSegmentGetData(it.seg);
len = osSegmentGetSize(it.seg); if (!osExtAppIsValid(app, len)) continue;
appCount++; /* it is safe to erase a running app; *erasemerelysetsaflagintheheader,
* and app keeps running until it is stopped */ if (doErase && osExtAppErase(app))
eraseCount++;
task = osTaskFindByAppID(app->hdr.appId); if (task) {
taskCount++; if (osStopTask(task, false))
stopCount++;
}
}
SET_COUNTER(stat.app, appCount);
SET_COUNTER(stat.task, taskCount);
SET_COUNTER(stat.op, stopCount);
SET_COUNTER(stat.erase, eraseCount);
staticvoid osScanExternal()
{ struct SegmentIterator it;
osSegmentIteratorInit(&it); while (osSegmentIteratorNext(&it)) { switch (osSegmentGetState(it.seg)) { case SEG_ST_EMPTY: // everything looks good
osLog(LOG_INFO, "External area is good\n"); return; case SEG_ST_ERASED: case SEG_ST_VALID: // this is valid stuff, ignore break; case SEG_ST_RESERVED: default: // something is wrong: erase everything
osLog(LOG_ERROR, "External area is damaged. Erasing\n");
osEraseShared(); return;
}
}
}
osSegmentIteratorInit(&it); while (osExtAppFind(&it, func, data)) {
app = osSegmentGetData(it.seg);
len = osSegmentGetSize(it.seg);
// skip erased or malformed apps if (!osExtAppIsValid(app, len)) continue;
appCount++;
checkIt = it; // find the most recent copy while (osExtAppFind(&checkIt, matchAppId, &app->hdr.appId)) { if (osExtAppErase(app)) // erase the old one, so we skip it next time
eraseCount++;
app = osSegmentGetData(checkIt.seg);
}
if (osTaskFindByAppID(app->hdr.appId)) { // this either the most recent external app with the same ID, // or internal app with the same id; in both cases we do nothing
taskCount++; continue;
}
staticvoid osStartTasks(void)
{ conststruct AppHdr *app;
uint32_t i, nApps; struct Task* task;
uint32_t status = 0;
uint32_t taskCnt = 0;
osLog(LOG_DEBUG, "Initializing task pool...\n");
list_init(&mTasks);
list_init(&mFreeTasks); for (i = 0; i < MAX_TASKS; ++i) {
task = &mTaskPool.data[i];
list_init(&task->list);
osFreeTask(task);
}
mSystemTask = osAllocTask(); // this is a dummy task; holder of TID 0; all system code will run with TID 0
osSetCurrentTask(mSystemTask);
osLog(LOG_DEBUG, "System task is: %p\n", mSystemTask);
/* first enum all internal apps, making sure to check for dupes */
osLog(LOG_DEBUG, "Starting internal apps...\n"); for (i = 0, app = platGetInternalAppList(&nApps); i < nApps; i++, app++) { if (!osIntAppIsValid(app)) {
osLog(LOG_WARN, "Invalid internal app @ %p ID %016" PRIX64 "header version: %" PRIu16 "\n",
app, app->hdr.appId, app->hdr.fwVer); continue;
}
if (!(app->hdr.fwFlags & FL_APP_HDR_INTERNAL)) {
osLog(LOG_WARN, "Internal app is not marked: [%p]: flags: 0x%04" PRIX16 "; ID: %016" PRIX64 "; ignored\n",
app, app->hdr.fwFlags, app->hdr.appId); continue;
} if ((task = osTaskFindByAppID(app->hdr.appId))) {
osLog(LOG_WARN, "Internal app ID %016" PRIX64 "@ %p attempting to update internal app @ %p; app @%p ignored.\n",
app->hdr.appId, app, task->app, app); continue;
} if (osStartApp(app))
taskCnt++;
}
switch (evt) { case EVT_SUBSCRIBE_TO_EVT: case EVT_UNSUBSCRIBE_TO_EVT: /* get task */
task = osTaskFindByTid(da->evtSub.tid); if (!task) break;
for (j = 0; j < da->evtSub.numEvts; j++) { /* find if subscribed to this evt */ for (i = 0; i < task->subbedEvtCount && task->subbedEvents[i] != da->evtSub.evts[j]; i++);
/* if unsub & found -> unsub */ if (evt == EVT_UNSUBSCRIBE_TO_EVT && i != task->subbedEvtCount)
task->subbedEvents[i] = task->subbedEvents[--task->subbedEvtCount]; /* if sub & not found -> sub */ elseif (evt == EVT_SUBSCRIBE_TO_EVT && i == task->subbedEvtCount) { if (task->subbedEvtListSz == task->subbedEvtCount) { /* enlarge the list */
uint32_t newSz = (task->subbedEvtListSz * 3 + 1) / 2;
uint32_t *newList = heapAlloc(sizeof(uint32_t[newSz])); /* grow by 50% */ if (newList) {
memcpy(newList, task->subbedEvents, sizeof(uint32_t[task->subbedEvtListSz])); if (task->subbedEvents != task->subbedEventsInt)
heapFree(task->subbedEvents);
task->subbedEvents = newList;
task->subbedEvtListSz = newSz;
}
} if (task->subbedEvtListSz > task->subbedEvtCount) { /* have space ? */
task->subbedEvents[task->subbedEvtCount++] = da->evtSub.evts[j];
}
}
} break;
/* send this event to all tasks who want it */
for_each_task(&mTasks, task) { if (task != ssTask) { for (i = 0; i < task->subbedEvtCount; i++) { if (task->subbedEvents[i] == newEvt) {
osTaskHandle(task, newEvt, OS_SYSTEM_TID, &ssMsg); break;
}
}
}
} break;
case EVT_DEFERRED_CALLBACK:
da->deferred.callback(da->deferred.cookie); break;
void osFreeRetainedEvent(uint32_t evtType, void *evtData, TaggedPtr *evtFreeingInfoP)
{ //TODO: figure the way to calculate src tid here to pass to handleEventFreeing
handleEventFreeing(evtType, evtData, *evtFreeingInfoP);
}
/* get an event */ if (!evtQueueDequeue(mEvtsInternal, &evtType, &evtData, &evtFreeingInfo, true)) return;
/* by default we free them when we're done with them */
mCurEvtEventFreeingInfo = &evtFreeingInfo;
tid = EVENT_GET_ORIGIN(evtType);
evt = EVENT_GET_EVENT(evtType);
if (evt < EVT_NO_FIRST_USER_EVENT) { /* handle deferred actions and other reserved events here */
osInternalEvtHandle(evtType, evtData);
} else { /* send this event to all tasks who want it */
for_each_task(&mTasks, task) { for (j = 0; j < task->subbedEvtCount; j++) { if (task->subbedEvents[j] == evt) {
osTaskHandle(task, evt, tid, evtData); break;
}
}
}
}
/* free it */ if (mCurEvtEventFreeingInfo)
handleEventFreeing(evtType, evtData, evtFreeingInfo);
/* avoid some possible errors */
mCurEvtEventFreeingInfo = NULL;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.26Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.