OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Вторник, 19 Март, 2024 04:58

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 97 ]  На страницу Пред.  1, 2, 3, 4, 5  След.
Автор Сообщение
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 04 Январь, 2007 20:07 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2449
Откуда: Россия, Томск
Хочу заметить, что имена новых процедур модуля 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.

Опубликованный интерфейс - это навсегда, поэтому я считаю, что этому вопросу следует уделить максимальное внимание как можно раньше.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 04 Январь, 2007 23:06 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 18:08
Сообщения: 76
Классная вещь Ваш Active BlackBox !!! :D Работает гораздо лучше чем Services.Action - с помощью него делаю обмен по netbios, среда зависает при 2-х действиях (клиент и сервер) с Services.now и одним таймером Services.DoLater(timer, Services.Ticks() + x), где x = 50..400.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 04 Январь, 2007 23:38 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Хорошо, давайте обсудим детали интерфейса!
Я согласен, что к релизу все должно быть вылизано.
По поводу перфикса c... - инерция, осталось с самых первых версий ядра. Префикс какой-то лучше бы ввести, т.к. группа процедур управления задачами довольно обширна, а ядро и так не мелкое по кол-ву экспортированных процедур.
Я приведу имена к стандарту.
По поводу больших букв модуля Ao - дело в том, что эти процедуры являются управляющими конструкциями, они модифицируют логику выполнения программы в точке своего вызова, и это должно быть подчеркнуто каким-либо образом (например, RETURN и EXIT выделяются не только большими, но даже жирными буквами). Заметьте, такие процедуры, как Sleep и т.п. не сделаны заглавными, только ACTIVE, EXCLUSIVE и UPDATE,
Есть еще другой момент - модуль Ao после апробации в текущем варианте является кандидатом в псевдомодули, как уже отметил выше, кажется, Ivor.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 05 Январь, 2007 02:23 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4695
Откуда: Россия, Орёл
Более чем кандидатом, ему придется им стать. Мы это уже обсуждали.

Кстати, одну интересную штуку так никто и не усек...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 05 Январь, 2007 13:45 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 18:08
Сообщения: 76
Борис Рюмшин писал(а):
Более чем кандидатом, ему придется им стать. Мы это уже обсуждали.

Кстати, одну интересную штуку так никто и не усек...

Какую?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 05 Январь, 2007 19:03 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4695
Откуда: Россия, Орёл
А вот не скажу. :) Вредный я. Не беспокойтесь, это не критическая уязвимость и не ошибка.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Среда, 17 Январь, 2007 14:10 

Зарегистрирован: Вторник, 04 Июль, 2006 13:04
Сообщения: 88
Откуда: Novosibirsk
Илья Ермаков писал(а):
ведутся работы по развитию и применению ББ для серверных систем, в частности, построению на нем распределенной СУБД и т.п. - и вот в этих продуктах мы уже не можем завязываться на GPL.

вот вот как раз в простых серверах и интерес... лицензия типа BSD? как у minix3? про миникс3 советую почитать, интересные штуки пишут...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Среда, 24 Январь, 2007 05:32 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Вообще, по сравнению с Active Oberon кое-что потерялось - блоки BEGIN {EXCLUSIVE} ... END. Это не вызывает дополнительных накладных расходов?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Среда, 24 Январь, 2007 10:37 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4695
Откуда: Россия, Орёл
Интересно, как Вы их предлагаете реализовать без расширения языка? :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Среда, 24 Январь, 2007 10:46 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 10:37
Сообщения: 875
Откуда: Россия, Владивосток
Никак, ясное дело. Но создание псевпомодуля AO - то же расширение языка, хоть и замаскированное.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Среда, 24 Январь, 2007 18:45 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4695
Откуда: Россия, Орёл
Ivor писал(а):
Никак, ясное дело. Но создание псевпомодуля AO - то же расширение языка, хоть и замаскированное.


Правильно мыслите... :D


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Среда, 28 Февраль, 2007 22:43 

Зарегистрирован: Среда, 28 Февраль, 2007 00:08
Сообщения: 142
Откуда: Нижний Новгород
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 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Скоро приобрету двухъядерку и оттестирую.
Скоро буду заниматься переносом нового ядра на Линукс - как раз еще раз перепроверю весь код синхронизации.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 18 Май, 2007 15:04 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Собсьно, новости по багу на мультиядерных системах...

Виснет только графический интерфейс, ошибка в реализации синхронизации с ГУЕм 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, 8);
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 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Сам я уезжаю на конференцию на неделю, отвечать на вопросы буду потом...

Резюме: активное ядро и основную "механику" можно считать стабильной. Можно готовить релиз. Предупреждаю, что имена процедур и вообще интерфейс сильно изменится...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 12 Июль, 2007 09:43 

Зарегистрирован: Среда, 17 Январь, 2007 03:59
Сообщения: 225
Илья Ермаков писал(а):
Резюме: активное ядро и основную "механику" можно считать стабильной. Можно готовить релиз. Предупреждаю, что имена процедур и вообще интерфейс сильно изменится...


А когда планируется ActiveBlacbox из beta в релиз?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 12 Июль, 2007 16:15 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Совместно с линуксовым ядром. Видимо, сначала релиз будет в линуксовой версии.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Active BlackBox 1.5 beta
СообщениеДобавлено: Вторник, 01 Январь, 2008 18:13 

Зарегистрирован: Вторник, 01 Январь, 2008 16:19
Сообщения: 35
у вас в системах таймауты для функций вроде AWait...и прочей синхронизации предусмотрены?
если нет - систему можно выкидывать.
можно себе легко представить наглухо зависший тред чтения с дискеты, которой нет в дисководе. или дисковод просто дуба дал.
НИКАКАЯ МОНОПОТОЧНОСТЬ без таймаутов не может работать в принципе. не..верней как дема, она работать может. но быть надежной - НИКОГДА.
кстати порочность многопоточности и синхронизации реализованной прямо в языке - в возможном отсутствии таймаутной концепции.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Active BlackBox 1.5 beta
СообщениеДобавлено: Вторник, 01 Январь, 2008 18:32 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
А как Вы себе представляете таймауты для высокоуровневых примитивов без обработки исключений?

В примере с дискетой никто не мешает иметь задачу-супервизор, которая по прошествии этого таймаута принудительно завершает задачу чтения с дискеты.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Active BlackBox 1.5 beta
СообщениеДобавлено: Вторник, 01 Январь, 2008 18:54 

Зарегистрирован: Вторник, 01 Январь, 2008 16:19
Сообщения: 35
Цитата:
В примере с дискетой никто не мешает иметь задачу-супервизор, которая по прошествии этого таймаута принудительно завершает задачу чтения с дискеты.

???
вы писали сложные многаааатредовые системы?
откуда ваш "супервизор" знает - застрял некий тред или нет?
это знает только сам тред. то есть тот программер, что его написал.
или у вас супервизор будет настолько умен, что станет выискивать застрявшие треды и снимать их общим образом??? а может мой тред запустил какую-от задачу в сети и ждет час пока она будет решена? а другой вообще не может ждать и полсекунды, ибо от этого зависит стабильность работы системы.
подумайте.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 97 ]  На страницу Пред.  1, 2, 3, 4, 5  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB