OberonCore https://forum.oberoncore.ru/ |
|
Active BlackBox https://forum.oberoncore.ru/viewtopic.php?f=31&t=354 |
Страница 3 из 5 |
Автор: | Александр Ильин [ Четверг, 04 Январь, 2007 20:07 ] |
Заголовок сообщения: | |
Хочу заметить, что имена новых процедур модуля Kernel грубо нарушают принятые в BlackBox соглашения. См. "Docu/BB-Rules.odc", раздел 8 (Case) и 9 (Names). Цитаты: "A procedure name always starts with a capital letter, this is true for procedure constants, types, variables, parameters, and record fields"; "A proper procedure has a verb as name, e.g. DrawDot"; "A function procedure has a noun or a predicate as name, e.g. NewObject(), IsEmpty(q)". Другими словами, мне сильно не нравится перфикс "с". Это нечитабельно. Все процедуры поименованы словно переменные. Аналогичные претензии к модулю Synch с его методами из заглавных букв. Заглавные буквы ведь используются для зарезервированных слов, распознаваемых компилятором. Если это попытка имитировать ключевые слова Active Oberon, то это только вводит в заблуждение знакомых с ним людей. Работа была проделана огромная, но не должно же в результате знакомства с ней складываться впечатление, что эта значимость дополнительно раздута с помощью клавиши Shift. Опубликованный интерфейс - это навсегда, поэтому я считаю, что этому вопросу следует уделить максимальное внимание как можно раньше. |
Автор: | Cardinal [ Четверг, 04 Январь, 2007 23:06 ] |
Заголовок сообщения: | |
Классная вещь Ваш Active BlackBox !!! Работает гораздо лучше чем Services.Action - с помощью него делаю обмен по netbios, среда зависает при 2-х действиях (клиент и сервер) с Services.now и одним таймером Services.DoLater(timer, Services.Ticks() + x), где x = 50..400. |
Автор: | Илья Ермаков [ Четверг, 04 Январь, 2007 23:38 ] |
Заголовок сообщения: | |
Хорошо, давайте обсудим детали интерфейса! Я согласен, что к релизу все должно быть вылизано. По поводу перфикса c... - инерция, осталось с самых первых версий ядра. Префикс какой-то лучше бы ввести, т.к. группа процедур управления задачами довольно обширна, а ядро и так не мелкое по кол-ву экспортированных процедур. Я приведу имена к стандарту. По поводу больших букв модуля Ao - дело в том, что эти процедуры являются управляющими конструкциями, они модифицируют логику выполнения программы в точке своего вызова, и это должно быть подчеркнуто каким-либо образом (например, RETURN и EXIT выделяются не только большими, но даже жирными буквами). Заметьте, такие процедуры, как Sleep и т.п. не сделаны заглавными, только ACTIVE, EXCLUSIVE и UPDATE, Есть еще другой момент - модуль Ao после апробации в текущем варианте является кандидатом в псевдомодули, как уже отметил выше, кажется, Ivor. |
Автор: | Борис Рюмшин [ Пятница, 05 Январь, 2007 02:23 ] |
Заголовок сообщения: | |
Более чем кандидатом, ему придется им стать. Мы это уже обсуждали. Кстати, одну интересную штуку так никто и не усек... |
Автор: | Cardinal [ Пятница, 05 Январь, 2007 13:45 ] |
Заголовок сообщения: | |
Борис Рюмшин писал(а): Более чем кандидатом, ему придется им стать. Мы это уже обсуждали.
Кстати, одну интересную штуку так никто и не усек... Какую? |
Автор: | Борис Рюмшин [ Пятница, 05 Январь, 2007 19:03 ] |
Заголовок сообщения: | |
А вот не скажу. Вредный я. Не беспокойтесь, это не критическая уязвимость и не ошибка. |
Автор: | CheshireCat [ Среда, 17 Январь, 2007 14:10 ] |
Заголовок сообщения: | |
Илья Ермаков писал(а): ведутся работы по развитию и применению ББ для серверных систем, в частности, построению на нем распределенной СУБД и т.п. - и вот в этих продуктах мы уже не можем завязываться на GPL.
вот вот как раз в простых серверах и интерес... лицензия типа BSD? как у minix3? про миникс3 советую почитать, интересные штуки пишут... |
Автор: | Иван Горячев [ Среда, 24 Январь, 2007 05:32 ] |
Заголовок сообщения: | |
Вообще, по сравнению с Active Oberon кое-что потерялось - блоки BEGIN {EXCLUSIVE} ... END. Это не вызывает дополнительных накладных расходов? |
Автор: | Борис Рюмшин [ Среда, 24 Январь, 2007 10:37 ] |
Заголовок сообщения: | |
Интересно, как Вы их предлагаете реализовать без расширения языка? |
Автор: | Иван Горячев [ Среда, 24 Январь, 2007 10:46 ] |
Заголовок сообщения: | |
Никак, ясное дело. Но создание псевпомодуля AO - то же расширение языка, хоть и замаскированное. |
Автор: | Борис Рюмшин [ Среда, 24 Январь, 2007 18:45 ] |
Заголовок сообщения: | |
Ivor писал(а): Никак, ясное дело. Но создание псевпомодуля AO - то же расширение языка, хоть и замаскированное.
Правильно мыслите... |
Автор: | batyrmastyr [ Среда, 28 Февраль, 2007 22:43 ] |
Заголовок сообщения: | |
O.Nick писал(а): Илья Ермаков писал(а): Скажите, еще вот что: в момент зависания Вы просматриваете информацию о потоках, т.е. пользуетесь окошками "Active Tasks", "Task Info" и т.п.? Потому что предположительно проблема именно там. В ядре достаточно сложный механизм доступа к информации о задачах, и много ошибок уже было исправлено. Иногда использовал, но закономерностей не улавил. Мне повезло больше:Core2 Duo закономерности есть в 4.3 "Экслюзивные и обновляющие процедуры" пример виснет при попытке печати чисел в лог: 1. при открытом Opened Tasks (число ядер-любое). (без него - работает). 2. модификация ObxAoBufferLint Код: PROCEDURE (b: Buffer) Put* (x: LONGINT), NEW;
BEGIN Ao.UPDATE; WHILE ~ (b.n # LEN(b.data)) DO Ao.[color=red]UPDATE[/color] END; (* буфер неполон *) b.data[(b.h+b.n) MOD LEN(b.data)] := x; INC(b.n) END Put; работает некотрое время при одном ядре и открытом Opened Tasks. (на двух - виснет сразу). 1й замер при 5869 (второе ядро), второй при 17000 и 5000 (при 12000 переключил с 1-го ядра на второго и пустил второй поток) В любом случае потоки убиваются только через Abort (в других примерах такого пока незамечал) |
Автор: | Илья Ермаков [ Четверг, 01 Март, 2007 03:26 ] |
Заголовок сообщения: | |
Скоро приобрету двухъядерку и оттестирую. Скоро буду заниматься переносом нового ядра на Линукс - как раз еще раз перепроверю весь код синхронизации. |
Автор: | Илья Ермаков [ Пятница, 18 Май, 2007 15:04 ] |
Заголовок сообщения: | |
Собсьно, новости по багу на мультиядерных системах... Виснет только графический интерфейс, ошибка в реализации синхронизации с ГУЕм Synch.BeginOberonSafe. Сейчас пока не исправлял, но пример, в котором обновление отображения шариков выполняется не из отдельной активной процедуры Update, а классически по Action, работает вроде как безошибочно: Код: (* Листинг 4.6 *)
MODULE ObxAoRoomsViews; IMPORT Ao, Synch, RoomsModels := ObxAoRoomsModels, Ports, Views, Models, Controllers, Stores, ObxRandom, Services; CONST minVersion = 0; maxVersion = 0; leftButton = 16; rightButton = 18; (* from HostPorts *) CONST timeResolution = 50; (* промежуток времени в мс, через который производится перерисовка отображения *) TYPE View = POINTER TO RECORD (Views.View) tag: Ao.MONITOR; stop: Ao.Stop; model: RoomsModels.Model; ua: UpdateAction END; UpdateAction = POINTER TO RECORD (Services.Action) v: View END; PROCEDURE (v: View) Restore (f: Views.Frame; l, t, r, b: INTEGER); CONST objectR = 2*Ports.mm; VAR w, h: INTEGER; unit: REAL; runner: RoomsModels.Runner; room: RoomsModels.Room; x, y, angle, vel: REAL; BEGIN v.context.GetSize(w, h); unit := MIN(w / v.model.w, h / v.model.h); f.DrawRect(0, 0, SHORT(ENTIER(v.model.w * unit)), SHORT(ENTIER(v.model.h * unit)), 0, Ports.blue); runner := v.model.Runners(); WHILE runner # NIL DO runner.GetState(x, y, angle, vel); f.DrawOval(SHORT(ENTIER(x*unit)) - objectR, SHORT(ENTIER(y*unit)) - objectR, SHORT(ENTIER(x*unit)) + objectR, SHORT(ENTIER(y*unit)) + objectR, -1, runner.color); runner := runner.next END; room := v.model.Rooms(); WHILE room # NIL DO f.DrawRect(SHORT(ENTIER(room.x*unit)), SHORT(ENTIER(room.y*unit)), SHORT(ENTIER((room.x+room.w)*unit)), SHORT(ENTIER((room.y+room.h)*unit)), 2*f.unit, Ports.blue); room := room.next END; Services.DoLater(v.ua, Services.Ticks() + timeResolution) END Restore; PROCEDURE (v: View) HandleCtrlMsg (f: Views.Frame; VAR msg: Controllers.Message; VAR focus: Views.View); VAR n, w, h: INTEGER; unit: REAL; x, y, angle, vel: REAL; r, t, l, b, res: INTEGER; PROCEDURE InputRect; (* Считываем прямоугольник для новой комнаты *) VAR x, y, x0, y0, res: INTEGER; mod: SET; isDown: BOOLEAN; BEGIN f.Input(x, y, mod, isDown); l := x; t := y; res := -1; REPEAT x0 := x; y0 := y; f.Input(x, y, mod, isDown); IF (x # x0) OR (y # y0) THEN f.RestoreRect(0, 0, w, h, FALSE); f.DrawRect(MIN(l, x), MIN(t, y), MAX(l, x), MAX(t, y), 0, Ports.blue) END; Ao.Sleep(50) UNTIL ~isDown; IF x < l THEN r := l; l := x ELSE r := x END; IF y < t THEN b := t; t := y ELSE b := y END END InputRect; BEGIN WITH msg: Controllers.TrackMsg DO v.context.GetSize(w, h); unit := MIN(w / v.model.w, h / v.model.h); IF leftButton IN msg.modifiers THEN IF Controllers.modify IN msg.modifiers THEN n := 10 ELSE n := 1 END; WHILE n > 0 DO x := msg.x / unit; y := msg.y / unit; angle := ObxRandom.Uniform()*360; vel := 50 + 600 * ObxRandom.Uniform(); v.model.NewRunner(SHORT(ENTIER(0FFFFFFH * ObxRandom.Uniform())), x, y, angle, vel); DEC(n) END ELSIF rightButton IN msg.modifiers THEN f.SaveRect(0, 0, w, h, res); InputRect; f.RestoreRect(0, 0, w, h, TRUE); v.model.NewRoom(l / unit, t / unit, (r - l) / unit, (b - t) / unit) END; Views.Update(v, Views.keepFrames) ELSE END END HandleCtrlMsg; PROCEDURE (v: View) ThisModel(): Models.Model; BEGIN RETURN v.model END ThisModel; PROCEDURE (a: UpdateAction) Do ; BEGIN Views.Update(a.v, Views.keepFrames) END Do; PROCEDURE New* (): Views.View; VAR v: View; m: RoomsModels.Model; a: UpdateAction; BEGIN m := RoomsModels.New(500, 500); NEW(v); v.model := m; Stores.Join(v, m); NEW(a); a.v := v; v.ua := a; Services.DoLater(a, Services.Ticks() + timeResolution); RETURN v END New; PROCEDURE Deposit* ; BEGIN Views.Deposit(New()) END Deposit; PROCEDURE (v: View) CopyFromModelView- (source: Views.View; model: Models.Model); VAR a: UpdateAction; BEGIN WITH source: View DO v.model := model(RoomsModels.Model); NEW(a); a.v := v; v.ua := a; Services.DoLater(a, Services.Ticks() + timeResolution) END END CopyFromModelView; PROCEDURE (v: View) Externalize- (VAR wr: Stores.Writer); BEGIN wr.WriteVersion(minVersion); wr.WriteStore(v.model) END Externalize; PROCEDURE (v: View) Internalize- (VAR rd: Stores.Reader); VAR ver: INTEGER; m: Stores.Store; a: UpdateAction; BEGIN rd.ReadVersion(minVersion, maxVersion, ver); IF ~rd.cancelled THEN rd.ReadStore(m); v.model := m(RoomsModels.Model); NEW(a); a.v := v; v.ua := a; Services.DoLater(a, Services.Ticks() + timeResolution) END END Internalize; END ObxAoRoomsViews. Так же кое-что исправил в модуле Ao - там действительно была очередь FILO, исправил на FIFO. Цитата: MODULE Ao;
(** project = "Active BlackBox" organization = "blackbox.metasystems.ru" contributors = "OCSE Metasystems, Ltd." version = "1.5 beta, based on BlackBox 1.5" copyright = "Docu/Active/About" license = "Docu/Active/License" changes = "" issues = "" **) IMPORT Kernel, Synch, Mem, Details, S := SYSTEM, HostSynch; CONST idle* = {0}; low* = {1}; high* = {0, 1}; bound* = {2}; copyRefs* = {3}; safe* = {4}; notCloseTask* = {5}; (* awaitOrComplete* = {6}; *) CONST regEax = 0; regEbx = 3; regEsi = 6; regEdi = 7; regFp = 5; regSp = 4; TYPE StartInfo = POINTER TO RECORD flags: SET; body: PROCEDURE; params: POINTER TO ARRAY OF BYTE; refs: POINTER TO ARRAY OF POINTER TO ARRAY OF BYTE; locals: POINTER TO ARRAY OF BYTE; ebx, esi, edi: INTEGER; barrier: Synch.CriticalSection; continue: BOOLEAN END; Stack = RECORD base, fp, sp: INTEGER END; Stop* = RECORD stop: BOOLEAN END; Await = POINTER TO RECORD next: Await; sem: Synch.Semaphore END; MONITOR* = POINTER TO RECORD (Details.Detail) locker: INTEGER; cs: Synch.CriticalSection; update: BOOLEAN; await, end: Await END; TLS = POINTER TO RECORD flags: SET; sp: INTEGER; exclStack: ARRAY 128 OF RECORD ret: INTEGER; object: MONITOR END END; AwaitHeap = POINTER TO RECORD (Mem.SynchedHeap) END; VAR tls: Synch.LocalStorage; awaitHeap: AwaitHeap; heapCS: Synch.CriticalSection; PROCEDURE [code] JmpEbx 0FFH, 0E3H; (*FF 11 100 011 (EBX) *) PROCEDURE [code] PushEbp 55H; PROCEDURE [code] MovEbpEsp 8BH, 0ECH; PROCEDURE [code] PopEbp 5DH; PROCEDURE [code] MovEspEbp 8BH, 0E5H; PROCEDURE [code] PushEdi 57H; PROCEDURE [code] PushEsi 56H; PROCEDURE [code] PushEbx 53H; PROCEDURE [code] PushEax 50H; PROCEDURE [code] PopEsi 5EH; PROCEDURE [code] PopEdi 5FH; PROCEDURE [code] PopEbx 5BH; PROCEDURE [code] PopEax 58H; PROCEDURE [code] Ret 0C3H; PROCEDURE [code] Ret8 0C2H, 08H, 00H; PROCEDURE [code] Push0 6AH, 00H; PROCEDURE [code] AddEsp12 83H, 0C4H, 0F4H; PROCEDURE [code] AddEsp24 83H, 0C4H, 0E8H; PROCEDURE [code] LeaEspEbp12 8DH, 65H, 0F4H; PROCEDURE CopyParams (IN this: Stack; IN info: Mem.ProcInfo; VAR new: StartInfo; flags: SET; OUT ok: BOOLEAN); VAR p, par, a, len, i, k: INTEGER; tag: Kernel.Type; adrs, offs: ARRAY 32 OF INTEGER; (* proc desc *) ref: INTEGER; mode, form: SHORTCHAR; desc: Kernel.Type; x: INTEGER; name: Kernel.Name; BEGIN ok := TRUE; IF info.nOfPars > 0 THEN flags := flags * copyRefs; NEW(new.refs, info.nOfPars); (* chek varpar params *) FOR par := 0 TO info.nOfPars-1 DO ref := info.refFirstPar; Kernel.GetRefVar(ref, mode, form, desc, x, name); offs[par] := x; IF (mode = 3X) OR (form = 12X) & (desc.size = 0) THEN p := this.fp + x; S.GET(p, a); IF (this.base >= a) & (a >= this.fp) THEN (* if varpar points to current stack... *) IF flags = {} THEN ok := FALSE; RETURN ELSIF flags = copyRefs THEN IF form = 11X THEN S.GET(p+4, tag); len := tag.size ELSIF form = 12X THEN IF desc.size = 0 THEN len := 1; FOR i := 1 TO desc.id DIV 16 MOD 16 DO S.GET(p+4*i, k); len := len * k END; len := len * Mem.TypeSize(desc.base[0]) ELSE len := desc.size * Mem.TypeSize(desc.base[0]) END ELSE len := MAX(Mem.SizeOfPar(1X, form, NIL), 4) END; NEW(new.refs[par], len); S.MOVE(a, S.ADR(new.refs[par][0]), len); adrs[par] := S.ADR(new.refs[par][0]) END ELSE adrs[par] := a END ELSE adrs[par] := 0 END END; (* copy params *) NEW(new.params, info.parEnd - info.parBeg); S.MOVE(this.fp + info.parBeg, S.ADR(new.params[0]), info.parEnd - info.parBeg); (* fixup varpars *) FOR par := 0 TO info.nOfPars-1 DO IF adrs[par] # 0 THEN S.PUT(S.ADR(new.params[0]) + offs[par] - info.parBeg, adrs[par]) END END END END CopyParams; PROCEDURE CopyLocals (IN this: Stack; VAR new: StartInfo); VAR len: INTEGER; BEGIN len := this.fp - this.sp; IF len > 0 THEN NEW(new.locals, len); S.MOVE(this.sp, S.ADR(new.locals[0]), len) END END CopyLocals; PROCEDURE ^ Starter2 (self: INTEGER; inf: ANYPTR); PROCEDURE ^ Restore (id: INTEGER; info: ANYPTR; OUT restored: BOOLEAN); (* 20 - wrong flags 21 - unknown caller module 22 - unexpected local reference 23 - too many param 24 - can not be bound *) PROCEDURE ACTIVE* (flags: SET); VAR ebx, esi, edi: INTEGER; new: StartInfo; stackSize: INTEGER; ret, stackUp, fpUp: INTEGER; this: Stack; info: Mem.ProcInfo; (* proc info *) procAdr: INTEGER; procName: Kernel.Name; id: INTEGER; ok: BOOLEAN; obj: ANYPTR; BEGIN S.GETREG(regEbx, ebx); S.GETREG(regEsi, esi); S.GETREG(regEdi, edi); NEW(new); new.ebx := ebx; new.esi := esi; new.edi := edi; new.barrier := Synch.dir.NewCS(); new.barrier.ENTER; new.flags := flags; Kernel.cGetTaskStack(Kernel.cThisTask(), this.base, this.fp, this.sp); this.sp := this.fp + 8; (* get sp of caller proc *) S.GET(this.fp+4, new.body); (* get addr of caller proc ACTIVE section (RET addr of this proc) *) S.GET(this.fp, this.fp); (* get frame of caller proc *) S.GET(this.fp+4, ret); (* get RET addr of caller proc *) Mem.GetProcInfo(S.VAL(INTEGER, new.body), info); ASSERT(Mem.firstStmt IN info.ext, 20); Kernel.GetRefProc(info.ref, procAdr, procName); CopyParams(this, info, new, flags, ok); ASSERT(ok, 24); CopyLocals(this, new); stackSize := 4000H; IF new.params # NIL THEN INC(stackSize, LEN(new.params)) END; IF new.locals # NIL THEN INC(stackSize, LEN(new.locals)) END; Kernel.cCreateTask(Starter2, new, stackSize, "Active proc: " + procName, FALSE, id); Kernel.cSetNativeMod(id, info.mod); IF flags * bound = bound THEN IF (info.nOfPars = 0) OR ~(Mem.object IN info.ext) THEN new.barrier.LEAVE; HALT(21) END; S.GET(this.fp + 8, obj); ASSERT(obj # NIL, 22); Kernel.cSetTaskOwner(id, obj); obj := NIL END; IF flags * safe = safe THEN Kernel.cSetTaskRestore(id, Restore, NIL) END; IF flags * {0, 1} = idle THEN Kernel.cSetPriority(id, Kernel.priorIdle) ELSIF flags * {0, 1} = low THEN Kernel.cSetPriority(id, Kernel.priorBelowNormal) ELSIF flags * {0, 1} = high THEN Kernel.cSetPriority(id, Kernel.priorAboveNormal) END; new.continue := TRUE; new.barrier.LEAVE; stackUp := this.fp + info.parEnd; (* deleting params of caller proc *) DEC(stackUp, 4); (* ACTIVE param size, for RET n. *) S.GET(this.fp, fpUp); S.PUT(stackUp-4, ret); S.PUT(stackUp-8, fpUp); S.PUTREG(regFp, stackUp-8); S.PUTREG(0, 0) (* Clear return value in AX *) END ACTIVE; (* Old starter *) PROCEDURE Starter2 (self: INTEGER; inf: ANYPTR); VAR ret, fp, sp, len, newFp: INTEGER; end, ok: BOOLEAN; t: TLS; PROCEDURE FixRet; VAR fp: INTEGER; BEGIN S.GETREG(regFp, fp); S.GET(fp + 4, ret) END FixRet; BEGIN end := FALSE; WITH inf: StartInfo DO inf.barrier.ENTER; inf.barrier.LEAVE; IF ~inf.continue THEN Kernel.cCloseTask(self, ok) END; t := tls.Get()(TLS); t.flags := inf.flags; S.GETREG(regSp, sp); S.GETREG(regFp, fp); FixRet; IF ~end THEN end := TRUE; IF inf.params # NIL THEN len := LEN(inf.params); S.MOVE(S.ADR(inf.params[0]), sp - len, len); DEC(sp, len) END; S.PUT(sp - 4, ret); S.PUT(sp - 8, fp); DEC(sp, ; newFp := sp; IF inf.locals # NIL THEN len := LEN(inf.locals); S.MOVE(S.ADR(inf.locals[0]), sp - len, len); DEC(sp, len) END; S.PUT(sp-4, inf.body); DEC(sp, 4); S.PUTREG(regEbx, inf.ebx); S.PUTREG(regEsi, inf.esi); S.PUTREG(regEdi, inf.edi); S.PUTREG(regSp, sp); S.PUTREG(regFp, newFp); Ret (* go to active procedure body *) ELSE IF inf.flags * notCloseTask = {} THEN Kernel.cCloseTask(self, ok) END END END END Starter2; PROCEDURE Restore (id: INTEGER; info: ANYPTR; OUT restored: BOOLEAN); BEGIN restored := TRUE END Restore; PROCEDURE (VAR s: Stop) Stop*, NEW; BEGIN s.stop := TRUE END Stop; PROCEDURE (VAR s: Stop) ShouldStop* (): BOOLEAN, NEW; BEGIN RETURN Kernel.cShouldComplete(Kernel.cThisTask()) OR s.stop END ShouldStop; PROCEDURE (VAR s: Stop) Reset*, NEW; BEGIN s.stop := FALSE END Reset; PROCEDURE Sleep* (ms: INTEGER); BEGIN Kernel.cSleep(ms) END Sleep; PROCEDURE Turn* ; BEGIN Kernel.cTurn END Turn; PROCEDURE (m: MONITOR) Init- (obj: ANYPTR); BEGIN Details.AssertSingle(obj, m); m.locker := -1; m.cs := Synch.dir.NewCS() END Init; PROCEDURE (h: AwaitHeap) New (): Await; VAR a: Await; BEGIN NEW(a); a.sem := HostSynch.NewSysSemaphore(0); (* Synch.dir.NewSem(0); *) RETURN a END New; PROCEDURE (h: AwaitHeap) Utile (ptr: ANYPTR); BEGIN WITH ptr: Await DO ptr.next := NIL END END Utile; (* Old ret hook *) PROCEDURE RetHook; END RetHook; PROCEDURE [noframe] RetHookNF ; VAR t: TLS; mon: MONITOR; aw: Await; ret, fp: INTEGER; BEGIN PushEbp; (* Reserve place for ret addr substitution *) PushEax; PushEdi; PushEsi; PushEbp; MovEbpEsp; Push0; Push0; AddEsp12; Push0; t := tls.Get()(TLS); ASSERT(t.sp > 0, 100); DEC(t.sp); mon := t.exclStack[t.sp].object; ret := t.exclStack[t.sp].ret; IF mon.update THEN aw := mon.await; WHILE aw # NIL DO aw.sem.POST(1); aw := aw.next END; mon.await := NIL; mon.end := NIL; mon.update := FALSE END; mon.locker := -1; mon.cs.LEAVE; S.GETREG(regFp, fp); S.PUT(fp+16, ret); MovEspEbp; PopEbp; PopEsi; PopEdi; PopEax; Ret END RetHookNF; (* 20 - wrong caller signature; 21 - recursive lock *) PROCEDURE EXCLUSIVE* ; VAR inf: Mem.ProcInfo; ret: INTEGER; obj: ANYPTR; mon: MONITOR; fp, adr: INTEGER; t: TLS; BEGIN S.GETREG(regFp, fp); S.GET(fp+4, ret); Mem.GetProcInfo(ret, inf); ASSERT(Mem.firstStmt IN inf.ext, 20); ASSERT(Mem.object IN inf.ext, 21); S.GET(fp, adr); S.GET(adr + 8, obj); ASSERT(obj # NIL, 22); mon := Kernel.ThisDetail(obj, S.VAL(Kernel.Type, S.TYP(MONITOR)))(MONITOR); obj := NIL; ASSERT(mon # NIL, 23); mon.cs.ENTER; IF mon.locker = Kernel.cThisTask() THEN mon.cs.LEAVE; HALT(24) END; t := tls.Get()(TLS); t.exclStack[t.sp].object := mon; S.GET(fp, fp); S.GET(fp + 4, t.exclStack[t.sp].ret); INC(t.sp); S.PUT(fp + 4, S.ADR(RetHookNF)); mon.locker := Kernel.cThisTask() END EXCLUSIVE; PROCEDURE UPDATE* ; VAR inf: Mem.ProcInfo; ret: INTEGER; obj: ANYPTR; mon: MONITOR; fp, adr: INTEGER; t: TLS; BEGIN S.GETREG(regFp, fp); S.GET(fp+4, ret); Mem.GetProcInfo(ret, inf); ASSERT(Mem.firstStmt IN inf.ext, 20); ASSERT(Mem.object IN inf.ext, 21); S.GET(fp, adr); S.GET(adr + 8, obj); ASSERT(obj # NIL, 22); mon := Kernel.ThisDetail(obj, S.VAL(Kernel.Type, S.ADR(MONITOR)))(MONITOR); obj := NIL; ASSERT(mon # NIL, 23); mon.cs.ENTER; mon.update := TRUE; IF mon.locker = Kernel.cThisTask() THEN mon.cs.LEAVE; HALT(24) END; t := tls.Get()(TLS); t.exclStack[t.sp].object := mon; S.GET(fp, fp); S.GET(fp + 4, t.exclStack[t.sp].ret); INC(t.sp); S.PUT(fp + 4, S.ADR(RetHookNF)); mon.locker := Kernel.cThisTask() END UPDATE; PROCEDURE Exit; VAR t: TLS; i: INTEGER; mon: MONITOR; BEGIN t := tls.Get()(TLS); FOR i := t.sp-1 TO 0 BY -1 DO mon := t.exclStack[i].object; mon.locker := -1; mon.cs.LEAVE END; t.sp := 0 END Exit; (* 20 - wrong caller signature; 21 - call form non-exclusive block *) PROCEDURE AWAIT* ; VAR fp, ret: INTEGER; inf: Mem.ProcInfo; obj: ANYPTR; mon: MONITOR; await: Await; t: TLS; ok: BOOLEAN; BEGIN S.GETREG(regFp, fp); S.GET(fp+4, ret); Mem.GetProcInfo(ret, inf); ASSERT(Mem.object IN inf.ext, 21); S.GET(fp, fp); S.GET(fp + 8, obj); ASSERT(obj # NIL, 22); mon := Kernel.ThisDetail(obj, S.VAL(Kernel.Type, S.ADR(MONITOR)))(MONITOR); obj := NIL; (* To prevent anchor until wait *) ASSERT(mon # NIL, 23); ASSERT(mon.locker = Kernel.cThisTask(), 24); t := tls.Get()(TLS); (* IF (awaitOrComplete * t.flags # {}) & Kernel.cShouldComplete(Kernel.cThisTask()) THEN Exit; Kernel.cCloseTask(Kernel.cThisTask(), ok) END; *) await := awaitHeap.Alloc()(Await); IF mon.end = NIL THEN mon.await := await ELSE mon.end.next := await END; mon.end := await; (* Unlock exclusive section *) mon.locker := -1; mon.cs.LEAVE; await.sem.WAIT; (* Re-enter exclusive section *) mon.cs.ENTER; mon.locker := Kernel.cThisTask(); awaitHeap.Free(await); (* Only after all other awaits signalled, to prevent await.next destroing *) (* IF (awaitOrComplete * t.flags # {}) & Kernel.cShouldComplete(Kernel.cThisTask()) THEN Exit; Kernel.cCloseTask(Kernel.cThisTask(), ok) END *) END AWAIT; PROCEDURE TrapChecker; BEGIN Exit END TrapChecker; PROCEDURE Init; VAR t: TLS; await: Await; BEGIN NEW(t); tls := Synch.dir.NewStorage(t); NEW(await); NEW(awaitHeap); awaitHeap.Init(0) END Init; BEGIN Init; Kernel.InstallTrapGlobalChecker(TrapChecker) CLOSE Kernel.RemoveTrapGlobalChecker(TrapChecker) END Ao. P.S. А модификатор [code] дерется с тегом [code] форума ) |
Автор: | Илья Ермаков [ Пятница, 18 Май, 2007 15:08 ] |
Заголовок сообщения: | |
Сам я уезжаю на конференцию на неделю, отвечать на вопросы буду потом... Резюме: активное ядро и основную "механику" можно считать стабильной. Можно готовить релиз. Предупреждаю, что имена процедур и вообще интерфейс сильно изменится... |
Автор: | Штирлиц [ Четверг, 12 Июль, 2007 09:43 ] |
Заголовок сообщения: | |
Илья Ермаков писал(а): Резюме: активное ядро и основную "механику" можно считать стабильной. Можно готовить релиз. Предупреждаю, что имена процедур и вообще интерфейс сильно изменится...
А когда планируется ActiveBlacbox из beta в релиз? |
Автор: | Илья Ермаков [ Четверг, 12 Июль, 2007 16:15 ] |
Заголовок сообщения: | |
Совместно с линуксовым ядром. Видимо, сначала релиз будет в линуксовой версии. |
Автор: | merk [ Вторник, 01 Январь, 2008 18:13 ] |
Заголовок сообщения: | Re: Active BlackBox 1.5 beta |
у вас в системах таймауты для функций вроде AWait...и прочей синхронизации предусмотрены? если нет - систему можно выкидывать. можно себе легко представить наглухо зависший тред чтения с дискеты, которой нет в дисководе. или дисковод просто дуба дал. НИКАКАЯ МОНОПОТОЧНОСТЬ без таймаутов не может работать в принципе. не..верней как дема, она работать может. но быть надежной - НИКОГДА. кстати порочность многопоточности и синхронизации реализованной прямо в языке - в возможном отсутствии таймаутной концепции. |
Автор: | Илья Ермаков [ Вторник, 01 Январь, 2008 18:32 ] |
Заголовок сообщения: | Re: Active BlackBox 1.5 beta |
А как Вы себе представляете таймауты для высокоуровневых примитивов без обработки исключений? В примере с дискетой никто не мешает иметь задачу-супервизор, которая по прошествии этого таймаута принудительно завершает задачу чтения с дискеты. |
Автор: | merk [ Вторник, 01 Январь, 2008 18:54 ] |
Заголовок сообщения: | Re: Active BlackBox 1.5 beta |
Цитата: В примере с дискетой никто не мешает иметь задачу-супервизор, которая по прошествии этого таймаута принудительно завершает задачу чтения с дискеты. ??? вы писали сложные многаааатредовые системы? откуда ваш "супервизор" знает - застрял некий тред или нет? это знает только сам тред. то есть тот программер, что его написал. или у вас супервизор будет настолько умен, что станет выискивать застрявшие треды и снимать их общим образом??? а может мой тред запустил какую-от задачу в сети и ждет час пока она будет решена? а другой вообще не может ждать и полсекунды, ибо от этого зависит стабильность работы системы. подумайте. |
Страница 3 из 5 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |