kategoria: ANSI C
[#1] Zabawa taskami
Założyłem sobie taska funkcją CreateTask(), która bez problemu jest w stanie zapisywać do plików otwartych wcześniej przy pomocy fopen(). Ale jak tylko chcę strzelić fopen() w tasku, to Amiga mi zawisa albo crashuje. Ktoś ma pomysł, czemu tak się dzieje?

Korzystam z vbcc 0.9e. Kick 2.0, sprawdzane na 68020.
[#2] Re: Zabawa taskami

@teh_KaiN, post #1

Z Tasku nie można wywoływać funkcji biblioteki dos, tylko z Procesu! Proces ma załączony stdin, stdout i inne deskryptory, a Task nie.

Najpewniej fopen() próbuje odnieść się do tablicy deskryptorów.

Skorzystaj z funkcji CreateProc() lub CreateNewProc(), żeby utworzyć nowy Proces.

Ostatnia aktualizacja: 29.03.2017 09:54:54 przez Hexmage960
[#3] Re: Zabawa taskami

@Hexmage960, post #2

Dzięki za odpowiedź! Spróbuję wieczorem z procesami. Masz gdzieś info, gdzie w jednym miejscu można poczytać o procesach i taskach i o tym, co mogą a co nie? Nazewnictwo w tych kwestiach jest jeszcze dla mnie mgliste i szukałem bardziej czegoś w rodzaju wątków, niż procesu, jeśli skorzystać z definicji kierujących mainstreamowymi OSami.

Zastanawiam się tylko czemu fwrite wywoływane w tasku miało prawo działać na uchwytach plików, które były otwarte przez program główny.
[#4] Re: Zabawa taskami

@teh_KaiN, post #3

Poczytaj sobie o kodzie startowym Workbencha i Shella tutaj.

Poza tym autodoki do funkcji CreateTask() (amiga.lib), oraz CreateProc(), CreateNewProc() (dos.library) zawierają stosowne informacje.

Nota:
Jeśli chcesz by Twój program uruchomiony z Workbencha stał się Procesem i mógł korzystać z dos.library, musisz usunąć wiadomość Workbencha z portu struktury Process.

Tutaj jest opis struktury Task, a tutaj opis struktury Process, która jest rozszerzeniem Tasku.

Zazwyczaj kod startowy usuwa tą wiadomość, więc program automatycznie może korzystać z dos.

Ale według dokumentacji task utworzony przez CreateTask() nie może korzystać z dos i trzeba użyć funkcji do tworzenia procesów.

Zastanawiam się tylko czemu fwrite wywoływane w tasku miało prawo działać na uchwytach plików, które były otwarte przez program główny.

Domyślam się, że fwrite() korzysta z deskryptora, który znajduje się w tablicy deskryptorów programu głównego. Za to fopen() w nowym Tasku próbuje zarezerwować deskryptor z tablicy deskryptorów, która nie istnieje.

Nazewnictwo w tych kwestiach jest jeszcze dla mnie mgliste i szukałem bardziej czegoś w rodzaju wątków, niż procesu, jeśli skorzystać z definicji kierujących mainstreamowymi OSami.

Z wątkami trudno porównać mechanizm w Amidze. Wątki w systemach PC (Windows, Linux) to takie zubożone procesy, które współdzielą więcej informacji, można je prościej tworzyć, ale zaletą jest to, że mogą być wykonywane na różnych rdzeniach procesora.
[#5] Re: Zabawa taskami

@teh_KaiN, post #3

Nazewnictwo: w mainstreamowych systemach procesy mają osobne przestrzenie adresowe. Z tego punktu widzenia cały odpalony AmigaOS jest jednym procesem. To co w mainstreamie nazywane jest wątkiem, to jest amigowy proces. Czyli po mainstreamowemu AmigaOS to proces, a wszystkie pracujące w nim programy to wątki. W literaturze amigowej natomiast terminy „wątek” i „proces” są albo używane zamiennie, albo rozróżnienie jest takie, że coś odpalone przez system samodzielnie, albo przez działanie użytkownika, to nazywane jest procesem. Jeżeli zaś jakiś proces uruchamia procesy potomne, to są nazywane wątkami, mimo że technicznie są dokładnie na takim samym poziomie praw i dostępu jak rodzic. Na przykład w AmigaOS proces rodzic może (wskutek błędu programisty) się zakończyć zostawiając działający kod procesów potomnych w wolnej pamięci...

W AmigaOS „task” czyli zadanie to najprostsza postać kodu współdzielącego procesor. Od (amigowego) procesu różni się tym, że nie ma przypisanego środowiska dos.library, a więc nie może korzystać z I/O plikowego czy konsolowego. Zarówno tego na poziomie dos.library, jak i tego z biblioteki standardowej C (które jest nakładką na to pierwsze).

Narzut amigowego procesu nad amigowym zadaniem jest tak mały, że zadań się praktycznie nie używa, tworzy się po prostu proces, najczęściej funkcją CreateNewProc().
[#6] Re: Zabawa taskami

@Krashan, post #5

Nazewnictwo: w mainstreamowych systemach procesy mają osobne przestrzenie adresowe.

A czy nie jest tak, że w mainstreamowych systemach, gdzie jest ochrona pamięci procesy mają osobne przestrzenie adresowe? W Amidze, gdzie nie ma ochrony pamięci i procesy korzystają z tej samej przestrzeni, ale nie mogą (nie powinny) wchodzić sobie w drogę.

Innymi słowy proces w mainstreamowych systemach i proces w Amiga OS to jest to samo.

Zgoda, że wątki tworzone są w obrębie procesów i tu nie ma odpowiednika w Amiga OS.

Ostatnia aktualizacja: 29.03.2017 17:35:29 przez Hexmage960
[#7] Re: Zabawa taskami

@Hexmage960, post #6

>> w mainstreamowych systemach procesy mają osobne przestrzenie adresowe.

> A czy nie jest tak, że w mainstreamowych systemach, gdzie jest ochrona pamięci procesy mają osobne przestrzenie adresowe?

I gadaj tu z wariatem :-/
[#8] Re: Zabawa taskami

@Krashan, post #5

Zarówno jednemu jak i drugiemu ślicznie dziękuję za objaśnienia. Przydało się zwłaszcza to z tłumaczeniem na dzisiejszą (zaraz za to słowo oberwę po głowie) nomenkaturę. ;)

Pozostaje zapomnieć o taskach i tworzyć procesy. CreateNewProc niestety nie użyję bo V36 a KS1.3 ma się zbyt dobrze by go olać.

To teraz idąc dalej w gęstwinę - argument seglist wygląda strasznie. Jak rozumiem jest on po to, by z hunka wyciągnąć odpowiednią sekcję (segment) funkcją LoadSeg i rezultat przekazać tam?

To jest bardzo mocny overkill w porównaniu z tym co chcę zrobić. Najchętniej użyłbym czegoś o składni podobnej do CreateTask, ale żeby mi to odpaliło pełnoprawny wątek z uwspólnioną pamięcią z programem macierzystym, gdzie podałbym tylko wskaźnik na funkcję wejścia. Właściwie interesuje mnie dokładnie to, co oferuje CreateTask, ale z możliwością otwierania plików. ;)

Ostatnia aktualizacja: 29.03.2017 18:41:52 przez teh_KaiN
[#9] Re: Zabawa taskami

@Krashan, post #7

Hmm... chodziło mi to, że wyróżniłeś procesy w mainstream OS od Amiga OS ze względu na osobne przestrzenie adresowe. Zaś według mnie w Amidze procesy nie mają odrębnych przestrzeni tylko ze względu na brak ochrony pamięci. Poza tym procesy w mainstream OS i Amiga OS się nie różnią. Mam nadzieję, że wyraziłem się teraz jasno.
[#10] Re: Zabawa taskami

@teh_KaiN, post #8

CreateNewProc niestety nie użyję bo V36 a KS1.3 ma się zbyt dobrze by go olać.
Im bardziej będziemy go jako programiści olewać, tym szybciej przestanie mieć się dobrze. Kicka 3.0 miałem w A500 w 1993 roku... Niemniej, wracając do sedna, w dokumentacji do LoadSeg() masz napisane jak zrobić „oszukaną” seglistę z kodu, który i tak już masz w pamięci.
[#11] Re: Zabawa taskami

@Krashan, post #10

Też prawda, ale to by oznaczało, że moja A500 by już tego nie uciągnęła - flashkicka mam w częściach i nie mam kiedy zaprojektować pcb i zlutować do kupy, a na gotowca trochę nie mam kasy.

Poza tym, jak widać na załączonym obrazku, można się sporo nauczyć pisząc pod KS1.3.

Tak czy inaczej mój kod działa. Dzięki!
[#12] Re: Zabawa taskami

@teh_KaiN, post #8

To teraz idąc dalej w gęstwinę - argument seglist wygląda strasznie. Jak rozumiem jest on po to, by z hunka wyciągnąć odpowiednią sekcję (segment) funkcją LoadSeg i rezultat przekazać tam?

Nie ma się czego obawiać. Lista segmentów to bardzo prosta rzecz.

Pierwsza metoda:

Zewnętrzny plik wykonywalny:
Jak chcesz załadować program z pliku nazwany "Proces.exe" po prostu robisz LoadSeg("Proces.exe"); i rezultat podpinasz pod CreateProc()/CreateNewProc().

Druga metoda: (o której wspomniał Krashan)

Kod zawarty w programie:
Możesz też zrobić ręcznie niby-listę:

; Nagłówek segmentu:
		    DS.L    0	;Align to longword
		    DC.L    16	;Segment "length" (faked)
		    DC.L    0	;Pointer to next segment
		    ...start of code...

Na początku swojego kodu procesu powinieneś mieć taki nagłówek, a tuż za nim swój kod.

Jak wywołać swój program w C? Najlepiej będzie jak dopiszesz instrukcję skoku do własnej procedury, która ma się wykonywać w tym procesie za pomocą instrukcji JSR lub JMP i etykiety funkcji w C. Wymaga to wstawki asemblerowej.

Mam nadzieję, że nic nie pomyliłem.

Pamiętam jak analizowałem kiedyś kod gry Dune 2, to ona właśnie na początku tworzy listę segmentów, robi relokację i rozpakowuje kod i dane. Muszę przyznać bardzo mi się to podobało.
[#13] Re: Zabawa taskami

@Hexmage960, post #12

Zrobiłem tak:

typedef struct _tSeg {
	ULONG ulSegSize;   ///< sizeof(struct tCodeHeader)
	ULONG ulNextSeg;   ///< Must be NULL
	UWORD uwJumpInstr; ///< Set to 0x4EF9 (a jump instruction)
	void (*pFn)(void); ///< Pointer to the function
} tSeg;

const tSeg s_sFakeSeg = {sizeof(tSeg), 0, 0x4EF9, workerMain};

// Gdzieś w kodzie
pResult = CreateProc(
	"OpenFire init proc", 0,
	((ULONG)&s_sFakeSeg.ulNextSeg) >> 2,
	WORKER_STACK_SIZE
);


I śmiga. Po co jest shr nie pytajcie mnie. Znalazłem gdzieś na jakiejś zapyziałej grupie dyskusyjnej i działa. Jak macie pomysły po co on tam jest, to chętnie posłucham. ;)
[#14] Re: Zabawa taskami

@teh_KaiN, post #13

>>2 jest dlatego, że jest to typ BPTR. Naleciałość z TRIPOSA czyli pierwowzoru dos.lib. Gdzieś w inkludach były chyba makra do zamiany normalnego wskaźnika na BPTR i odwrotnie.
[#15] Re: Zabawa taskami

@kiero, post #14

Ha, o tym nie wiedziałem. Makra znalazłem w dos.h:

/* Convert BPTR to typical C pointer */
#ifdef OBSOLETE_LIBRARIES_DOS_H
#define BADDR( bptr )	(((ULONG)bptr) << 2)
#else
/* This one has no problems with CASTing */
#define BADDR(x)	((APTR)((ULONG)(x) << 2))
#endif
/* Convert address into a BPTR */
#define MKBADDR(x)	(((LONG)(x)) >> 2)
[#16] Re: Zabawa taskami

@teh_KaiN, post #15

Przeczytałem w AmigaDOS Manual, że BPTR jest przesunięty dlatego by mieć zawsze pewność, że adres będzie podzielny przez 4.
[#17] Re: Zabawa taskami

@Hexmage960, post #16

Przeczytałem w AmigaDOS Manual, że BPTR jest przesunięty dlatego by mieć zawsze pewność, że adres będzie podzielny przez 4.


BPTR jest przesuniety dlatego ze w BCPL (w ktorym byl napisany TRIPOS i poczatkowo AmigaODS) byl tylko jeden typ danych: slowo (WORD) ktore bylo 32 bitowe. Adresowalo sie nie bajty w pamieci, a slowa, wiec wskaznik sila rzeczy byl przesuniety...

AmigaDOS odziedziczyl tego potworka lacznie z nietypowym typem BSTR
[#18] Re: Zabawa taskami

@mschulz, post #17

Dzięki za info, warto wiedzieć!
[#19] Re: Zabawa taskami

@Hexmage960, post #18

Zabawy taskami to jednak nie koniec i wracamy do pierwotnego problemu ;)

Czytam sobie pliki w amigowym procesie własnymi funkcjami opartymi o fopen, co do których jestem pewien. Testowałem swój kod na kicku 2.04. Działa super. Potem testuję na KS1.3. Fopen wyrzuca nulla, nawet jak zrobię samo otwarcie i zamknięcie pliku to też. Potem startuję grę z flopa pod kickiem 1.3 i działa. Wczoraj Softiron mi mówi, że ma ten sam problem na kicku 3. O co chodzi? Stawiam że pewnie dlatego, że w tym procesie nie otwieram dos.library, ale jak je otworzyć, by nie pogryzło się z tym otwartym przez środowisko uruchomieniowe głównego procesu?

Problem zredukowałem do samego użycia fopen więc to nie kwestia złych funkcji. Plik istnieje i otwarcie go chwilę wcześniej z rodzica nie sprawia problemów. Fclose używam.
[#20] Re: Zabawa taskami

@teh_KaiN, post #19

Jeżeli tworzysz wątki, zwłaszcza robiąc to pod KS 1.3, zapomnij, że w C istnieje coś takiego jak biblioteka standardowa. Otwórz sobie w wątku dos.library, a potem z niej użyj Open() i Read(). Żeby funkcje I/O z biblioteki standardowej działały, kod startowy dołączny przez kompilator zawiera ładne kilkanaście kB kodu, które jest wykonywane przed wejściem do main(). Proces potomny oczywiście przy swoim starcie tego kodu nie wykona i stąd problemy.
[#21] Re: Zabawa taskami

@Krashan, post #20

Przećwiczę to już po RKLE. Teraz po prostu zrobię wszystko na płaszczaka, bez wątków w rozumieniu "mainstreamowym".
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem