Shop OBEX P1 Docs P2 Docs Learn Events
Method to check for free cogs? — Parallax Forums

Method to check for free cogs?

T ChapT Chap Posts: 4,223
edited 2009-05-31 17:13 in Propeller 1
I am looking at the manual at cog related stuff, but don't see what looks like a method to at any given time poll the Propeller and return what cogs are currently used. What is a quick way to scan each cog to see who is occupied?

Comments

  • Robot FreakRobot Freak Posts: 168
    edited 2009-05-29 20:29
    I think that cognew returns the cog number of the new cog that is being used.
    You can save that in a variable for later use.

    Edit: see also 'cogid'
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-29 21:20
    Just keep calling cognew with a dummy program (i.e. solo repeat) until it fails to return a new cog. The cogids that it didn't return are the ones being used. Then return the cogs it started using cogstop.

    If you're doing this to find a cog number to use with coginit, please put this out of your mind posthaste. There is rarely, if ever, a good reason to use coginit. Always use cognew to start a new cog.

    -Phil
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-29 21:27
    What kind of program do you want to write that you can loose track of how many COGs you did start?

    There is no direct support for that - neither from SPIN nor from PASM. If you want to keep track of the started COGs you need a central place (say the end of RAM) to set a byte if you start a COG and clear it if the COG is stopped/stops itself. But for all the Object Exchange objects you use, you have to modify that code accordingly.

    Post Edited (MagIO2) : 5/29/2009 9:38:29 PM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-29 21:35
    If you know your program, why shouldn't you use coginit. Say your propeller runs a lot of COGs for driving different devices that you need all the time. One is left for accessing SD-card, EEPROM or other memory, why not start the currently needed PASM-code in exactly that COG - and restart that COG with another driver if needed?

    A cognew loop is nice to find out which COGs are left. You could start a very little PASM program that simply terminates immediately, so you don't have to waste SPIN-time to do a COGSTOP.
    var long cogfree
    
    repeat while cognew(@cogcount,0)<>-1
      cogfree++
    
    dat
               org 0
    
    cogcount   cogid   cogcount
               cogstop cogcount
    
    


    Post Edited (MagIO2) : 5/29/2009 9:46:26 PM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-29 23:22
    Using coginit is simply bad programming technique. If you think you have to use coginit, you need to rethink how your program is organized. For one thing, you may be using objects that someone else wrote and have no way of knowing ahead of time which cogs they've started. All cogs are identical, so there's no reason to prefer one over another. Therefore, keeping one's program cog number independent is always the best policy.

    -Phil
  • kuronekokuroneko Posts: 3,623
    edited 2009-05-30 01:04
    Phil Pilgrim (PhiPi) said...
    Using coginit is simply bad programming technique. If you think you have to use coginit, you need to rethink how your program is organized.
    I'm with MagIO on this one, if it does the job use it. However, I agree that it shouldn't be used if doesn't serve a purpose.

    ATM I'm in the progress of writing a driver which needs cogs synchronised in a way which can't be achieved with waitcnt & Co, e.g. I need 2 cogs which come out of their hub access window N cycles apart. This means I could pick the first one through cognew but the second one has to be by coginit. And allocating all currently available cogs and run tests for a matching pair is not an option.
  • T ChapT Chap Posts: 4,223
    edited 2009-05-30 01:08
    Thanks for the input fellows. Yes I was aware that you can use a variable to start each cog with, but there are instances of cogs calling other cogs/objects, which means a bit more work to track each cog, especially when they could be layers deep. What I was looking for was a fast easy way to look at any given time to see what cogs were available to check headroom when things may be getting called you are overlooking. For example, I just redid the piezo speaker object to run solely from within the method it is called from, as it is set up to call square wave in a new cog them quit after the beep. There were instances where the beep would launch multiple copies on top of each other without a clear explanation, other than beeping in a loop too fast perhaps, but it was shutting other cogs down. Maybe this is a rare case, but still a valid reason to look at cog usage. I'll run the loop magI02 posted in a few. Thanks.

    Post Edited (TChapman) : 5/30/2009 1:13:56 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-30 02:05
    kuroneko said...
    I'm with MagIO on this one, if it does the job use it.
    Well, I wouldn't go that far. Some otherwise well-structured computer languages provide a GOTO, but that's no reason to use it, even if it does the job.

    You may well have identified an exception to the no-coginit rule, however, but it's hard to tell without more info. And, to be honest, I've used it myself — once — in a bootloader, but only because some end-users may have certain (unreasonable) expectations about which cog their top-level program starts in.

    Although I may be one of the more outspoken critics of coginit, I'm certainly not alone. This exchange, for example, may help to illustrate the point. (Sorry, Chip. Sometimes, ya just gotta call in the big guns! smile.gif I hope you haven't changed your mind in the meantime.)

    -Phil
  • heaterheater Posts: 3,370
    edited 2009-05-30 05:47
    Phil and Co: Ultimately, in general, theoretically isn't it true that it is impossible to check for free COGs?.

    1. Assume neither you or your COG checker program has any knowledge of the other programs that may be running in the Prop. They are "black boxes".

    2. Assume there is a COG checker that returns a list of free COGS (or even just the first free COG). Lets say using Phils technique or whatever.

    3. The caller of the COG checker would now like to use one of the reported free COGs.

    BUT in the time between steps 2) and 3) the rest of the application (in the black box) may well have already started to use that very COG. BANG your app is dead.

    On this basis it looks to be that if you have to check for free COGs your in trouble.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-30 06:05
    In trouble? Not necessarily. The idea is to keep those cogs bound up until you've enumerated all of them. Then pick one, and use coginnit to insert your own code into it. Once this is done, you can free the others. But this would be an absurdly silly reason to do a free-cog inventory, since you could just start a new cog with cognew and be done with it. (Having to employ coginit should be caution enough that it's a bad idea.)

    So why would you need to inventory cog use? In a development environment, using foreign objects, it might provide info that ferreting out by analytic means would take longer to obtain. Or you might have an object that can start a variable number of cogs for speed or efficiency and use the inventory to optimise asset allocation dynamically. There may be other valid reasons; but using the info to pick and choose a free cog to start is not one of them.

    -Phil
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-30 19:09
    Hi Phil ... in general I am absolutely with you. DON'T USE COGINIT. It's bad practice, if you want to write some code which should be useful for others and end in the ObEx. BUT no rule without exception. Usually -whatever program you write- it is very likely that you have a main program which controls all other stuff. Let's now assume you have a VGA object (2 COGs), a serial interface (1 COG), a stepper motor driver (1 COG), a servo driver (1 COG) and a ADC object (1 COG) running which need to do their job all the time. You have 1 COG for the main program which glues everything together. So only one COG is left. And now you have to access EEPROM, SD card or you have some own PASM routines .... whatever ... from time to time. Why not start the stuff with coginit then? - instead of wasting processor-time for calling a stop routine and another start routine?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-30 20:17
    MagIO2,

    Why would you assume that a COGSTOP takes any significant time at all, or that a COGNEW takes more time than a COGINIT? But that's beside the point. If a cog routine is temporary and has to play nice with its timeshared cogmates, it should be programmed to exit gracefully rather than have to be suffocated with a COGINIT or bludgeoned to death with a COGSTOP. OTOH, suicide is okay. If a program wants to end its own cog life with a COGSTOP or COGINIT, that's fine and much preferred over having it imposed externally.

    I suppose it's a minor point; and, of course, there's never a rule without an exception; but in my mind a COGINIT, from a style standpoint, is no different than a GOTO. Sure, there are times when a GOTO might seem the quickest solution to a flow-of-control problem; but that's a slippery slope, and if there's a solution that doesn't involve such lack of finesse, it's always better — even if it involves a little more code or takes a little longer to execute.

    A program has to do more than just work. Style matters. And despite my loudly touted preferences, I don't want to be the arbiter of style. Programming style is a cultural phenomenon that evolves over time and can't be dictated — except by what gets included with, or excluded from, the language itself.

    -Phil
  • localrogerlocalroger Posts: 3,452
    edited 2009-05-30 21:28
    I have mixed feelings on this. Cog use can get murky, especially if you're using objects you don't completely understand yourself from the obex (and let's face it, we expect all n00bs to feel safe using things like the TV and keyboard drivers). So a cog inventory could be a useful thing. But I don't like the idea of dynamically stopping and restarting cogs. Really, I think you should be reclaiming the Hub RAM used by PASM routines when possible, on the theory that once you start something like a video or keyboard driver you know you'll never stop it. And if you run out of cogs, you should probably be looking at a multiblade solution instead of trying to juggle the 8 you have on one chip.
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-30 21:50
    This is what I mean with waste of time:
    1. call stop function of the driver I want to stop -> SPIN function call
    2. driver stop function uses cogstop -> SPIN instruction
    3. call start function of the driver I want to start instead -> SPIN function call
    4. driver start first calls stop in most cases or checks if COG already started -> SPIN function call / SPIN if statement
    5. driver start uses cogstart to run the COG-code -> SPIN instruction

    my version could be (it depends on whether I need that extra speed of course)

    1. call coginit with the driver I want to start using the COG-ID of the COG I want to stop



    Anyway ... if you want to know how many COGs are free at any time, here is how you can count:

    var
      long  cogcnt, freecogs
      
    pub cntFreeCOGs
    
     
        cogcnt:=8
        repeat until cognew(@cogret,@cogcnt)==-1
          cogcnt--
        freecogs:=8-cogcnt
        cogcnt:=0
         
    dat     org   0
    cogret
                  rdlong    outa, par wz
            if_nz jmp       #cogret
                  cogid     cogret
                  cogstop   cogret
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-30 22:04
    @logalroger:
    can't second this. We have 160MIPs under the hood. So, assuming you add some external RAM you can do very nice things with one Propeller. And depending on the system we talk about, it might be useful to get rid of a driver that you currently don't need and use it differently.

    I want to build some kind of couch potato device ;o) It will have a nice menu system with a lot of functions I currently can't even think of. So, when I select something from the menu it has to do something completely different than before. Why not get rid of the COGs that only have been started for the previous function and use em again? And why waste the code-space to implement a graceful shutdown? You need code in the main-controller to notify the COG that it should stop and you need code in the COG to recognize the notification. As long as we don't talk about a COG that writes to flash memory I don't see a good reason for that.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-30 22:18
    MagIO2,

    What you're forgetting is that the stop routines of many driver objects do more than just free a cog. There may also be some other housekeeping chores that have to be performed to effect a graceful exit. I'm sorry to disagree, but it's certainly not an approach I would use in my own programming.

    -Phil
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-30 22:33
    Phil,

    no need to apologize for disagreing. It's your opinion and mine is not so far away from yours. I only allow exceptions and you want to tell us that it's a devils tool. Again: NEVER use coginit in ObjectExchange code (here the hurdles for being a good reason of an exception are much higher ;o)
  • localrogerlocalroger Posts: 3,452
    edited 2009-05-30 23:34
    @MagIO2: Agreed one prop can do amazing things. But one prop also costs eight dollars. You mention external memory, which is interesting, because the thing about serially interfaced external memory is that SPI is a bus protocol and it can be shared. I know most of the focus here has been on transferring info prop to prop, but I have been looking at a more loosely coupled scheme where multiple props share SPI RAM and intercommunicate via stuff dropped there. Granted this wouldn't be video-fast, but it has other advantages such as not linking the timing of any cog in one prop to that of any cog in the others.

    The basic idea behind the prop is that you use cogs to do things that would be done by interrupt service routines in a more normal processor. Now quite often those things won't take all the available bandwidth; it certainly doesn't occupy a 20 MIPS processor full-time to read a keyboard, but in the prop that's the usual configuration. And the prop is cleverly built so that what you lose in MIPs, you gain in lessened power consumption as you WAITCNT. The four port serial driver is a clever exception but I think it IS an exception because virtual UARTs are a particularly simple case to emulate.

    Anyway, there's no point in us having a strenuous disagreement; each of us pursuing our focus is likely to develop tools the other might find surprisingly useful in unanticipated contexts. I think a cog inventory would be a useful thing, and it seems that this would benefit your programming style even more than mine. So getting back to the thread topic I'd guess we are pretty much in agreement.
  • T ChapT Chap Posts: 4,223
    edited 2009-05-31 06:08
    Just tested the newer cogfree code and seems to work fine. Thanks for posting that MagI02
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-31 16:59
    Welcome, but remember PhiPi does not allow you to use it ;o) The first try was a quick idea I posted - of course untested - but it already scetched the solution used in the second try.

    Another usecase for coginit - even for a driver: You have a driver where configuration changes periodicaly but the dirver is so busy that you don't want it to check for new config by itself.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-31 17:13
    MagIO2 said...
    You have a driver where configuration changes periodicaly but the dirver is so busy that you don't want it to check for new config by itself.
    Now come on. You're just trying to rile me! smile.gif If the driver is that busy, how is it that you can afford to take it out of operation long enough to completely restart it? It doesn't take that much time to do a rdbyte to see if new configuration data are available.

    -Phil
Sign In or Register to comment.