Suivez-nous sur X

|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Assembleur - lancer des fonctions multitâches
(Article écrit par Thomas Pimmel et extrait d'ANews - novembre 1999)
|
|
En attendant le nouveau Kickstart qui va révolutionner l'informatique du futur (le 3.10005), l'homme des cavernes a besoin de se
faire les crocs pour rester en forme.
Sur le rouleau de cire numérique collé à votre revue, vous trouverez bien sûr un source directement assemblable et incompréhensible
à souhait.
Mais revenons aux origines de l'homme : quand Dieu créa le multitâche et vit que cela était bon, il pensa aussi à créer l'Amiga,
sage précaution. Ainsi naquit la fonction CreateNewProc, dont le nom, prononcé à toute vitesse évoque le cri d'amour du rhinocéros
en phase d'ascension hormonale.
Cette fonction, une fois domestiquée et dressée, vous permet d'exécuter un sous-programme de façon multitâche.
C'est de cette façon qu'un modeleur affiche une vue "3D pleine" de votre objet tout en vous laissant la main, ou que la station
Mir se casse la gueule sur Paco tout en restant dans l'espace. J'admets que l'exemple est tiré par les cheveux. Je serai puni.
Voici maintenant, camarade homo sapiens sapiens, la liste des problèmes à résoudre avant d'y arriver :
- Il faut rendre le sous-programme réentrant, nous allons utiliser pour cela les variables locales du
mois dernier (et oui, mon gars, faut suivre).
- On doit pouvoir passer des paramètres à notre petit et pour ça, rien ne vaut un bon message d'exec.
- Enfin, il est hors de question de se barrer en laissant le petit tout seul, bande de tortionnaires vosgiens !
Imaginons un monde parfait : votre femelle qu'on appellera Rachelle par souci d'anonymat, est au bistrot avec ses potes.
On a donc toute la nuit devant nous avant qu'elle ne rentre en titubant et qu'elle ne se prenne les pieds dans le cordon
d'alimentation de votre Amiga.
Vous avez un joli programme, qui ne fait rien d'autre que d'attendre un message pour quitter ce monde de brutes. Il a ouvert
la dos.library et a rangé le pointeur dans une jolie variable dont le nom fait rêver : dos_base (rââââââââh !).
Un sous-programme, qui répond au nom de "PetitOursBrun", a été écrit. Il effectue une boucle de quelques billiards avant de rendre
l'âme d'un RTS pathétique.
Avant d'attendre le message, le programme principal appelle la sous-routine "PetitOursBrun", à l'aide de CreateNewProc dont
voici la syntaxe :
Ma grand-mère me la toujours dit : "Petit Tom, méfie-toi des syntaxes faciles, c'est après que les emmerdements arrivent".
La liste des tags va comprendre un point d'entrée dans votre programme (un pointeur sur "PetitOursBrun") et, c'est tout. Qu'est-ce
que tu dis de ça, grand-ma ?
LancePetitOurs
move.l #MesTags,d1
move.l dos_base,a6
jsr LVOCreateNewProc(a6)
…
MesTags
dc.l NP_Entry,PetitOursBrun
dc.l 0
|
Cette fonction renvoie un pointeur sur le "process" ou zéro, si l'Amiga a la flemme. Vous trouverez la liste des autres tags dans
dos/dostags.i.
Maintenant, il faut envoyer des paramètres à PetitOursBrun. Par exemple, un pointeur sur vos variables globales, le port de
message du programme principal et les résultats du match Excelsior/Charleroi. Pour cela, on va utiliser le port de message de la
tâche nouvellement créée.
STRUCTURE LeMessage,MN_SIZE
APTR lm_globalvar
APTR lm_replyport
SHORT lm_match
LABEL lm_sizeof
|
Il sera envoyé par le programme principal, à l'aide de la fonction PutMsg(port,message). La mémoire peut être libérée par lune des
deux tâches. Tout dépend des conventions que vous utilisez. Intuition se charge lui-même, par exemple, des messages qu'il a créés.
Moi, je préfère allouer mes messages à l'aide de la routine AllocVec et laisser le soin au destinataire de faire FreeVec.
Il est temps de jeter un coup d'oeil à l'exemple gravé sur le plat à tarte brillant vendu une fortune avec votre magazine :
*********************************
* Exemple de lancement *
* d'un S/P en multitâche *
* (c) Micro&Nenbourg *
* all consignes reserved *
*********************************
include exec/types.i
include exec/memory.i
include exec/ports.i
include varloc.i
include dos/dos.i
include dos/dostags.i
include dos/dosextens.i
include dos_lib.i
include exec_lib.i
STRUCTURE mesvariables,0
APTR dosbase
APTR msgport
LABEL varbase_sizeof
;======================
; Le Main()
;======================
Start
movem.l d2-7/a2-6,-(sp)
; init base
lea varbase,a4
; ouverture dos, alloc du port de message
bsr Init
tst.l d0
beq.s .quit
; lancement de PetitOursBrun
; (peut être lancé plusieurs fois,
; dans ce cas prévoir un compteur
; des tâches lancée)
bsr LancePetitOurs
tst.l d0
beq.s .quit
; Attendre
bsr Attendre
.quit
; tout libérer
bsr Libère
; on quitte
moveq #0,d0
movem.l (sp)+,d2-7/a2-6
rts
;======================
; Attendre()
;======================
Attendre
; wait, get, reply, comme d'hab
move.l msgport(a4),a0
move.l 4.w,a6
jsr _LVOWaitPort(a6)
move.l msgport(a4),a0
move.l 4.w,a6
jsr _LVOGetMsg(a6)
tst.l d0
beq.s Attendre
; réponse + free du message
move.l d0,a1
move.l a1,-(sp)
move.l 4.w,a6
jsr _LVOReplyMsg(a6)
move.l (sp)+,a1
move.l 4.w,a6
jsr _LVOFreeVec(a6)
rts
;======================
; LancePetitOurs()
;======================
; variables locales pour lancepetitours
STRUCTURE VarLocale,0
_APTR vl_message
_APTR vl_tâche
LABEL vl_sizeof
; structure du message
STRUCTURE LeMessage,MN_SIZE
APTR lm_globalvar
APTR lm_replyport
SHORT lm_match
LABEL lm_sizeof
LancePetitOurs
; init variables locales
_LINK a5,vl_sizeof
clr.l vl_message(a5)
clr.l vl_tâche(a5)
; alloc du message
move.l #lm_sizeof,d0
move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
move.l 4.w,a6
jsr _LVOAllocVec(a6)
move.l d0,vl_message(a5)
beq.s .erreur
; composition message
move.l vl_message(a5),a1
move.l a4,lm_globalvar(a1)
move.l msgport(a4),lm_replyport(a1)
move.l #$0201,lm_match(a1) ; L'Excel a gagné!
move.w #lm_sizeof,MN_LENGTH(a1)
; vu que le programme qui reçoit le message
; se charge du FreeVec, il est inutile
; d'avoir un port reply
; c'est un des avantages!
; MN_REPLYPORT = 0, yeah
; ceci permet d'utiliser le port de message
; de la tâche mère pour envoyer des infos
; tout au long de l'exec du fils :
; dessine-moi un mouton, casse-toi, etc.
; lancement de la tâche
move.l #OursTags,d1
move.l dosbase(a4),a6
jsr _LVOCreateNewProc(a6)
move.l d0,vl_tâche(a5)
beq.s .erreur
; envoi du message
move.l vl_tâche(a5),a0
lea pr_MsgPort(a0),a0 ; port
move.l vl_message(a5),a1
move.l 4.w,a6
jsr _LVOPutMsg(a6)
; on efface la variable message, c'est au fils de
; se demmerder
clr.l vl_message(a5)
.erreur
; libérer mémoire message si erreur
move.l vl_message(a5),a1
move.l 4.w,a6
jsr _LVOFreeVec(a6)
move.l vl_tâche(a5),d0
unlk a5
rts
OursTags
dc.l NP_Entry,PetitOursBrun
dc.l 0 ;TAG_END
;======================
; PetitOursBrun(globalvar, replyport, match)
;======================
STRUCTURE petitOurs,0
_APTR po_monport
_APTR po_reply
_APTR po_message
_SHORT po_match
LABEL po_sizeof
PetitOursBrun
_LINK a5,po_sizeof
; on récupère le message
bsr AttendMaman
; on attend un peu, histoire faire quelque chose
move.l dosbase(a4),a6
move.l #100,d1
jsr _LVODelay(a6)
; on répond à maman, elle peut quitter
bsr RépondAMaman
unlk a5
rts
;--------------
RépondAMaman
; alloc & composition du message (vide dans cet exemple)
move.l #MN_SIZE,d0
move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
move.l 4.w,a6
jsr _LVOAllocVec(a6)
move.l d0,po_message(a5)
beq.s .encore
move.l po_message(a5),a1
move.w #MN_SIZE,MN_LENGTH(a1)
; forbid sinon danger!
jsr _LVOForbid(a6)
; envoi du message, maman quittera lorsque fils éliminé (merci forbid!)
move.l po_reply(a5),a0
move.l po_message(a5),a1
move.l 4.w,a6
jsr _LVOPutMsg(a6)
rts
.encore
; le message doit partir sinon blocage!
move.l dosbase(a4),a6
move.l #25,d1
jsr _LVODelay(a6)
bra.s RépondAMaman
;--------------
AttendMaman
; on recherche mon port
move.l 4.w,a6
sub.l a1,a1
jsr _LVOFindTask(a6)
move.l d0,a0
lea pr_MsgPort(a0),a0
move.l a0,po_monport(a5)
.encore
; on attend le piti message
move.l po_monport(a5),a0
move.l 4.w,a6
jsr _LVOWaitPort(a6)
; on le cherche
move.l po_monport(a5),a0
move.l 4.w,a6
jsr _LVOGetMsg(a6)
tst.l d0
beq.s .encore
; on répond
move.l d0,a1
move.l lm_globalvar(a1),a4 ; on récupère les variables globales
move.l lm_replyport(a1),po_reply(a5)
move.w lm_match(a1),po_match(a5)
move.l 4.w,a6
jsr _LVOReplyMsg(a6)
rts
;======================
; Init()
;======================
Init
; allocation du grouic-grouic de message
move.l 4.w,a6
jsr _LVOCreateMsgPort(a6)
move.l d0,msgport(a4)
beq.s .rts
; ouverture de dos
lea dosname(pc),a1
moveq #0,d0
move.l 4.w,a6
jsr _LVOOpenLibrary(a6)
move.l d0,dosbase(a4)
.rts
rts
;======================
; Libère()
;======================
Libère
; freemem du port
move.l 4.w,a6
move.l msgport(a4),a0
jsr _LVODeleteMsgPort(a6)
; closelib
move.l dosbase(a4),a1
cmp.l #0,a1
beq.s .rts
move.l 4.w,a6
jsr _LVOCloseLibrary(a6)
.rts
rts
;======================
; Constantes
;======================
dosname dc.b 'dos.library',0
even
;======================
; Variables
;======================
section variables,bss
varbase ds.b varbase_sizeof
|
Je présume simplement les opérations : le programme principal ouvre la dos.library, alloue un port de message pour que
PetitOursBrun signale la fin de sa tâche. Il alloue et compose le message d'arguments. Il lance le sous-programme et envoie le message.
Puis, il attend tranquillement le message de retour de PetitOurs ou une panne de courant provoquée par Rachelle.
Maintenant, voyons ce que PetitOursBrun doit faire...
Il recherche l'adresse de son "process", grâce à la fonction FindTask(0). Il attend le message de MamanOurs, à l'aide de WaitPort.
Il fait son petit "reply", copie les paramètres et libère la mémoire occupée par le message de Maman.
Il fait ce pour quoi il a été conçu, puis décide de mettre fin à son existence. Non, ce n'est pas triste, c'est la vie, frère
Néandertalien. Avant de partir, il envoie à son tour un message à Maman, pour signaler qu'elle peut disparaître.
Bien sûr, PetitOurs aura pris la précaution de précéder son envoi par Forbid, de façon à ce que Maman ne quitte pas avant qu'Exec
ne supprime la tâche du fils.
Bien entendu, libre à vous d'organiser une correspondance plus suivie entre les deux tâches, ou encore de lancer la tâche fils
plusieurs fois. Une fois le principe compris, tout est possible.
C'est tout pour aujourd'hui. Vous pouvez fermer ce journal et vous occuper de Rachelle.
Vous pouvez aussi me joindre par courrier électronique : tpimmel@amiganews.com.
Inutile de me demander en mariage, c'est déjà fait. Par contre, si vous avez des questions, des insultes inédites, des propositions
amusantes, n'hésitez pas.
Le mois prochain, j'ignore totalement ce que je vais bien pouvoir écrire. Mais c'est ça l'aventure ! Vivre au jour le jour, siroter
du lait de coco fermenté au bord de la plage et sculpter des femmes nues en marbre...
|